まえおき
OpenGrok+Dockerで、使い捨てソース検索エンジンをつくる
https://qiita.com/YusukeIwaki/items/3f855202e9c00247d5c7
OpenGrokの公式Dockerイメージでソース検索サーバーを立てる
https://qiita.com/YusukeIwaki/items/ccf7dab6b1a284bbff26
と、Docker+OpenGrokでのソース検索サーバを建てるネタは放出してきたんだけども、
実のところ今までのソース検索は「30分に1度、インデックス再構築のために、4分くらいダウンタイムが発生する」という、大きな欠点があったことは伝えていなかった。
自分用のソース検索だったらそれでよかったんだけど、周りに使ってもらい始めると、30分に1回「なんかおかしいんですけど」って言われるリスクと戦わないといけないので、いい加減対処しようってなった。
ということで、今回はその欠点を解決した版を紹介しようと思う。
なぜダウンタイムが発生するのか
雑に絵で説明しよう。理由は2つある。
いままでの構成はこう。ソースコードはホスト側にあって、それをbindfsでDocker側にマウントする&Docker側でインデックスが保持される。
これだと、ソースコードを最新化するタイミングでまずインデックスと実ソースが微妙に不整合な状態になる。「検索結果には出てくるのに、実際に見に行くと最新ソースでは消されていたのでなくなっていた」みたいなことが起きる。
そんで、次に最大の問題であるダウンタイムが発生する。まだ出来上がってないインデックスを外からHTTPでアクセスしに来ちゃうからだ。
Dockerらしく、裏でインデックス作って、できあがったら差し替えればいいじゃない?
こんな感じで、裏でdocker buildしておいて、インデックス生成までdocker buildでやってしまって
イメージのビルドが終わったら、あとは好きなタイミングで、古いコンテナをstopして新しいコンテナをrunすれば、せいぜい2〜3秒程度のダウンタイムで済むんじゃないか?という発想。
公式Dockerイメージでは無理である
Oracle公式のopengrokのイメージは、docker runしたタイミングで初めてインデックス生成が行われる。
先に書いたように、HTTPを受け付けるにもかかわらずインデックスが出来上がってない状態、みたいなのが少なからずできてしまうので、これをそのまま使うことはできない。
仕方がないので、自前で用意することにした。
https://github.com/YusukeIwaki/docker-opengrok-alpine
https://github.com/oracle/opengrok/wiki/How-to-setup-OpenGrok の手順を参考にしつつ、
公式OpenGrokイメージの https://github.com/oracle/opengrok/blob/master/Dockerfile や https://github.com/oracle/opengrok/tree/master/docker を斜め読みして作成した。
Alpine Linuxの apk add --no-cache ctags
だとuniversal-ctagsじゃなくて古いほうのctagsが入るので、universal-ctagsを自前でビルドしないといけないのが微妙に厄介。
他は割とすんなり理解できるだろう。
裏でイメージをビルドする君をつくる
イメージのビルドスクリプトは、
- 最新のdevelopブランチでも変更がないなら、全部キャッシュを効かせたい
- 最新のdevelopブランチが変更されているなら、git cloneの直前まではキャッシュを効かせ、それ以降はビルドしたい
のようにする。
Dockerfileでgit clone を使う際にキャッシュをADDで回避
https://qiita.com/sawanoboly/items/ac559c43b9662304931a
で書かれているように、ADDでorigin/developのコミットハッシュを書いたファイルをコンテナに送り込むといい。
GitHub APIを使うでもいいし、
git ls-remote git@bitbucket.org:YusukeIwaki/some_repository.git refs/heads/develop | cut -f1 > origin_develop.sha1.txt
みたいな感じで愚直にファイルを作るでもいいと思う。
ビルド自体は、シンプルに docker build -t some-source-search .
するだけ。
コンテナを差し替える君をつくる
雑だが、
docker ps | grep "0.0.0.0:8080" | cut -f1 -d' ' | xargs --no-run-if-empty docker stop | xargs --no-run-if-empty docker rm
docker run -d -p 8080:8080 some-source-search
こんな感じでいける。
Rundeckでジョブ管理すると楽
- docker buildが終わり次第、コンテナの差し替えを行う
- 日中のインデックス更新は30分に1回おこなう
- ログは3日間分くらいは残しておきたい
などなど、cronで管理するのはいやなので、Rundeckにまかせてしまう。
https://www.rundeck.com/open-source
セットアップ方法は、ぐぐればでてくるので省略。
まとめ
切り替えは雑ですが、イミュータブルデプロイみたいなかんじの構成にすることで、かなり快適にソース検索ができるようになります。
公式OpenGrokイメージが似たようなDockerfileを提供してくれたら、もっとみんな幸せになるんじゃないかなぁ...。