サーバの CI ってどうするのが良いのでしょうね。現状やむを得ず行って
いますが、やり過ぎ感も否めないです。

[2014-09-14-1] に Wercker+Vagrant+EC2 の組み合わせでこのサーバの
CI を始めてから、[2015-02-08-2] に CircleCI+Vagrant+EC2 に変更しま
した。そして今回、CircleCI+Docker に変更しました。

理由は EC2 を使うのは大げさだと思い始めたからです。CI 時間の短縮を
期待しましたが、ほとんど変わりませんでした。結果的に、時々 EC2 イ
ンスタンスを起動するのに 30 分以上かかり、CircleCI のタイムアウト
時間を超える問題は解決出来ましたが。

Docker 入門できて自己満足は得られたのですが、Docker の使い方ではな
いなあというのが正直な感想です。

Docker を使ってサーバの CI をするためには、openssh-server をインス
トールする必要があります。そもそも Docker は一度インスタンスを作っ
たら変更を加えるべきではないため、Docker を起動してから knife-solo
で変更を加えるのは誤った使い方です。

このブログのサーバ(さくらの VPS)には nginx や td-agent、
elasticsearch などがごちゃごちゃと入ってますが、同じ環境を Docker
で作るのもおかしな話です。Docker は 1 サーバ 1 責務だと思うので、
例えば nginx だけをインストールする使い方が正しい気がします。

そういう意味で無理して CI しているなあと、モヤモヤしているところです。

修正内容はこちらです。末尾に解説を記載しました。

./script/bootstrap-docker.sh

このスクリプトは CircleCI の dependencies.pre で実行されます。
Docker に必要な環境がセットアップされます。

初回はキャッシュした Docker archive($HOME/cache/ubuntu.tar.gz)が
存在しないため、新規作成します。docker save 時に圧縮しているのは
CircleCI の容量削減のためです。400MB から 140MB 程度に削減出来まし
た。CI が速くなるかと思いましたが、そうでもありませんでした。

次回以降 Dockerfile を変更していなければ、キャッシュが使われます。
この判断に使われるのが、初回に作った $HOME/cache/Dockerfile.digest
です。docker load には圧縮した tar ball をそのまま読み込ませている
のがポイントです。マニュアル によると bzip2, xz 形式でも良いらしい
です。

$HOME/.ssh/config に設定を追加することで、"$ ssh ci-coker" で
Docker にログイン可能にしています。

Dockerfile

https://docs.docker.com/examples/running_ssh_service/
参考に作りました。

knife-solo や chef-solo で必要最低限のパッケージである curl,
openssh-server, rsync をインストールしています。

/root/.ssh/authorized_keys は ssh-keygen コマンドで作った公開鍵で
す。対応する秘密鍵は CircleCI の
https://circleci.com/gh/masutaka/server-masutaka.net/edit#ssh
登録しました。

Chef Client も https://docs.chef.io/install_omnibus.html の方法で
インストールしています。バージョンを指定しているのは、Gemfile.lock
の chef とバージョンを合わせやすくするためです。今後、自動 bundle
update の時に Dockerfile も自動更新させる予定です。

Docker の中で DOCKER_IN_CIRCLECI という自前の環境変数を有効にして
います。Docker の CI でどうしてもレシピの動作を変える必要があった
からです(モヤモヤ)。openjdk-7-jdk パッケージのインストール、ufw
の設定で使われているのが分かると思います。

circle.yml

Cook の後に以下の workaround を追加しました。

ssh ci-docker “/etc/init.d/mongodb start && /etc/init.d/td-agent start”
Cook で mongodb が起動せず、それに引きずられて td-agent も起動しな
いためです。Docker の制約だそうですが、mackerel-agent や nginx は
起動したのでその辺り謎です。

/etc/hostname

Cook で変更できなかったため、“atomic_update false” を追加しました。
ファイルロックがかかっていたと思います(うろ覚え)。

Thanks a lot!
CircleCI + DockerでサーバCI始めました|feedforce Engineers’ blog

追記(2015-09-21):
$ update-locale --reset LANG=ja_JP.UTF-8 で以下のエラーが出るよ
うになったので、EC2 に戻してしまいました。[2015-08-30-2] も影響は
Docker のみでした。やはり Docker とサーバの CI は合わないと思いました。

STDERR: *** update-locale: Error: invalid locale settings: LANG=ja_JP.UTF-8