要約
- WebSocketをいい感じに扱ってくれるミドルウェアkuiperbeltのDockerfileを作った
- Docker対応のために幾つかの事柄をやった
- オプションを環境変数で渡せるようにするとか
- あとまあいろいろやった
経緯
- YAPC::Okinawaで結構大々的に宣伝をした(つもり)なんだけれど、いろいろ残念なところを直しておきたいと思ったのでいろいろやっていた
README.md
のインストール方法が腐っているとか- Goは基本
go get
でコマンドインストールできる。けれどkuiperbeltはdepで依存ライブラリのバージョン固定をしており、go get
はそんなの無視して最新バージョン取ってきたりローカルにすでにあるバージョンを使おうとして、インターフェイスが変わるとコンパイルに失敗する - あと単体コマンドで動くやつはGoコンパイラは要らないので、release binaryを用いるのが吉。kuiperbeltは以前からこれを提供していた
- Goは基本
- ところでrelease binaryがあるツールはid:Songmuさん作のghgを用いると、OSやアーキテクチャを考慮してダウンロードしてくれるので便利ということが知られていますが、kuiperbeltはrelease binaryのパッケージングがghgに対応していなくて適用できてなかった
- というのをYAPC::Okinawaのスライドを書いている時に気がついた
- しかしパッケージングを変更すると会社の方で使われているアプリケーションで影響があるのでは?(chefレシピとか)と社内Slackで言ったら「それよりもDockerfileの変更がある」と言われて、たしかに今はDocker上で動かしているからそうか〜となった
- というわけでパッケージング変更と公式Dockerfile/docker imageの配布をすすめることにした
やったこと
パッケージング変更
- そういえばGoのツール作る時にビルドやらテストやらrelease binary上げるのとか毎回コピペやなって思った
- コピペでやるよりは自分用テンプレがあるとええやろと思い、作った
- 中身はdepとかクロスコンパイルツールgoxz、GitHub releaseに生成物を上げるghrとかをインストールしたり、所定のディレクトリに生成物をはいたり、それをアップロードするMakefileの雛形みたいなやつ
- アイディアの元ネタはArduino-Makefile
- これをkuiperbeltから使うようにした
- travisでビルドがうまく行かなかったりして試行錯誤の跡が見られる
- 最終的にはghrは使わずに、travisのdeploy機能を使ってタグ切られたらGitHub releaseに出すようにした
.travis.yml
もjetpackに入れるのはどうかなとは思っている- GitHub tokenの暗号化とかもあるので一発ではいけなさそう
- これでパッケージング変更したv1.2.6を出した
Dockerfile作成
- 課題として、Docker内で動作するkuiperbeltに対してオプションをどのように渡すかという問題がある
- 現状、kuiperbeltは数多くのオプションをyml形式で設定ファイルを記述することで行っている
- Docker containerで設定ファイルを必要とするアプリケーションは基本的にはボリュームマウントするか、イメージビルド時に含めてしまうか、はたまた起動時にS3からcurlスクリプトで引っ張ってくるとかそういうのが必要
- あと、コンテナ起動時の引数で渡す方法と、環境変数で渡す方法がある
- まあ環境変数でやるのが一番簡単
- しかし、たくさんのオプションを環境変数で使えるようにするのめんどいなってなる
- ところがkayac/go-configって言う便利なやつがあるっぽいのでそれを使うことにした。べんり
- あとは最近入ったmulti stage buildなんか使ってscratchイメージベースなので結構軽い。4MBです。お試しあれ
$ docker pull mackee/kuiperbelt:latest
- static buildしたGoバイナリってパフォーマンスにどれ位影響あるのだろうか。今度ベンチマークを取って試してみたい
サンプルアプリもdocker-composeで試せるようにする
- 簡単なチャットアプリが_example以下に元々入っている
- Perl/PSGI製
- PerlのPreforkサーバでも刺さらないWebSocketアプリケーションが書けるというのを示すためのもの
- sinatraとかflaskでも作ろうかなとは思っているけれどまだやる気が出ない
- ビルドするのに現代Perlの知識が必要だったので、これもDockerに押し込むことにした
- 具体的にはdocker-composeでkuiperbeltとデータストアとして利用するRedisを立てつつ、ローカルのPerlアプリケーションが動作するコンテナもビルドする
- 仕事で得た知識を使っていて、例えば依存が書かれたcpanfileだけをCOPYしておいてその上でcpmで依存入れた後に必要な
app.psgi
とかindex.html
をCOPYする戦法で行くと、依存の変更が無ければ全モジュールインストールし直しでビルド時間がなが~いにならない - 普段はこういう仕事を時々やってます
- 仕事で得た知識を使っていて、例えば依存が書かれたcpanfileだけをCOPYしておいてその上でcpmで依存入れた後に必要な
- あと立ててみたら不審な動作をしていたので、チャットメッセージのブロードキャスト部分を大幅に直した
- このコンテナも実は別タグでDockerHubから落とせます
$ docker pull mackee/kuiperbelt:webchat-example
- 今はBootstrap + jQueryで貧相な感じの見た目だけれど、Vue.jsとUIツールキットライブラリ使ってもっとまともな感じにはしたいと思っております
- 直している時に、そういえばXSSヤベーんじゃねと思ってネットでググって出てきたXSSロケーターなるものを入れてみたら案の定ポップアップして笑ったので、Perl側でHTML::Escape噛ました。あと、クライアントの生成したUUIDをそのまま使っているので、それを無視してPerl側でUUIDを生成するようにした。これでも大丈夫なんです
- クライアント側にはリトライ機構とか入ってないし、アイドルタイムアウトの機能も使ってないので、そのへんも手を入れたいけれど、JSの知識がない。
その辺の試行錯誤はこちら
https://github.com/mackee/kuiperbelt/pull/48github.com
試したい場合は、
$ git clone https://github.com/mackee/kuiperbelt $ cd kuiperbelt/_example $ make up $ make open
で終わりです。お試しあれ
DockerHubに上げる
- 当初、travisのdeployにあるのかなと思ってたけれど、そんなことはなくて、DockerHubからGitHubの連携やるとwebhookか何かで変更検知して自動ビルドしてくれるっぽい。便利
- タダ枠だからなのかしらないけれど、ビルドキュー入ってからイメージできるまでは結構時間がかかる
- というわけで公式イメージです
https://hub.docker.com/r/mackee/kuiperbelt/hub.docker.com
README.md更新
- ちょっとだけ気合を入れて書き換えた
- ところで英語はかなりできないです。トラウマがあるレベル
- 今回はGrammerlyとGoogle翻訳を併用しつつ書いたけれど、まだまだ意味不明な文があると思う。つらい
- どんな機能があるか分からんという声があったので、APIとCallbackのsummaryみたいなものを作ってみた
- 少しは見栄えが良くなったのではないのでしょうか
お知らせ
- kuiperbeltではユーザを募集しております
- 社内需要を満たすだけだと多様性がないもので。。。
- 使って作ってみたとかあれば教えてください
- どうぶつタワーバトルのコピーを習作として作りたいと去年末から思っておりますが、なかなか取り掛かれておりません
- あと見栄えのするロゴね……