皆さん Docker 使ってますか?
なんだかよくわかんないからいいや・・・ そんなふうに考えていた時期が俺にもありました。
ということで今回は身近な例として、ローカルマシン上で Docker を使って開発環境を構築した事例を紹介します。 どちらかというと、ぶっちぎってサーバサイド寄りの話でしかも管理寄りの話だったりもしますが、その他の方々にも何かお役に立てれば幸いです。
KLab にはたくさんの案件が有りますが、その中には WEBサーバやDBサーバなどが全部詰まった VM イメージを配布する、という方法でローカルの開発環境を提供している案件も有ります。 それらの案件も息が長くなり、下記のような状況が散見されるようになってきました。
その結果、チーム内メンバー間の環境の違いによるトラブル(テストが通らない等)が発生するというけしからん事態になってきました。
そこで、次の様な戦略でローカル開発環境をもっと簡単に管理していきましょう、というのが本論となります。
コードで管理する。環境の再現をコードで表しておくことで、管理が非常に楽になります。また、配布も git などのリポジトリ経由で気軽に行えるので、配布行為自体もラクになります。
個人の好みを配布物に含めない。コードを書く際のエディタやシェルその他(個人にとっての)便利ツールなどは完全に個人の好みの問題であるので、実行環境とは完全に切り離すべきです。 実行環境を不可侵にしておけば、心理的障壁はなくなるはずです。
上記のようにしておけば、気軽に作り直せるし、配布も簡単だし、良いことずくめです。
さて、KLab の場合 http を介したモバイルゲームサービスが主ですから、サーバサイドといってもユニットテストだけでなく、なるべく end-to-end なテストも存在します。 従って、開発環境としても WEB サーバや DB サーバなど、もろもろのサービスが必要となってきます。
これらのサービスをそれぞれ、別のコンテナとして立ち上げていくのが Docker 流のやり方です。 とはいえ、各サービスに対してちまちま docker
コマンドを叩いていたのでは埒が明きませんから、docker-compose
を利用して簡潔に管理できるようにしています。 例えば下記のような感じです。
docker-compose.yml.dist
web:
build: ./web
links: [db, memcached, redis]
volumes:
- %%SERVER_REPO_DIR%%:/app/src
- %%LOG_DIR%%:/var/log/www
ports: ["8080:80"]
ci:
build: ./ci
links: [web, db, memcached, redis]
volumes:
- %%SERVER_REPO_DIR%%:/app/src
command: sleep infinity
db:
build: ./db
memcached: { image: "memcached:1" }
redis: { image: "redis:2.6" }
このようにして、細かくイメージを作りこみたい場合は Dockerfile
を作成、それ以外はオフィシャルイメージを流用するなどして、サービス群の関連などと共に記述していきます。
docker ファミリーのインストールが済んでいれば、環境の構築やアップデートは、
docker-compose build
をたたくだけ)docker-compse up
をたたくだけ)を実行してもらうだけなので、実行環境の再現は非常に簡単です。
docker-compose.yml「.dist」 となっているのは、テンプレートとして使用しているためです。 マウントするパス(
%%
で囲まれている)は人によって異なるのが理由で、 本環境の導入時に、インストーラースクリプトを実行してもらう事によって実体を作成しています。
先述の「腐敗防止層」と名付けられた部分は、利用者が docker そのものを意識しなくてすむような、アダプタ的コマンド集の形をしています。 例えば、下記のようなインターフェイスを提供しています。
myenv build # docker-compose build などを集約
myenv up # docker-compose up などを集約
myenv server test --group Hoge # テストを実行する
myenv server init-db # DB の初期化 & test ready な状態にする
myenv server db-cli # DBのインタラクティブシェル
myenv server shell # バッチ実行用サーバを模したインタラクティブシェル
docker
や docker-compose
などのコマンドは便利ですが、細かいオプションや docker の概念などを短時間でマスターして下さい、というのも難しい話ですし、何より myenv
を実行環境への唯一のエントリーポイントとしておくことで、環境が育ってしまうことが避けられます。
開発に必須なツール達が色々なソフトウェアに依存していることもあると思います。 例えば、PHP がないと動かない composer など。 これらも全て docker 上で実行するようにスクリプト化しておけば、面倒な依存のインストールの負担をかけなくてすみます。
# 最小構成の例です。実運用では他にも git などが必要だったり、
# composer が作るキャッシュを volume して永続化するなどの工夫が必要になると思います。
echo 'FROM php:5.6-cli
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin
ENTRYPOINT ["composer.phar"]
' | docker build -t php-composer - > /dev/null
docker run -it --rm -v `pwd`:`pwd` -w `pwd` php-composer "$@"
このようにコマンド単位であっても dockerize して依存を少なくし、環境構築がすぱっといくようにしています。
Docker client は Windows でも動くようになりましたが、docker-compose は実は Windows をサポートしていません。 色々なやり方があるかもしれませんが、例えば boot2docker を使用している場合は、docker-compose
というイメージ名で docker/compose:Dockerfile をビルドしておけば、下記のように利用できます。
boot2docker ssh -t "docker run -it --rm -v `pwd`:`pwd` -v /var/run/docker.sock:/var/run/docker.sock -w `pwd` docker-compose $@"
イメージのビルドも含め、先ほどの myenv build
に組み込んでおけば、Windows でも大丈夫ですね!
Docker をどっかどっか使って、管理のしやすさを念頭に置いたローカル開発環境の事例を紹介しました。
今回紹介した事例では web サーバが動いていますので、サーバサイドの開発・テスト用途だけではなく、クライアント開発時の http API サーバとしても利用できます。 ここからさらに発展させて、クライアントのテスト実行環境、その他運用上必要なツールの開発に至る、案件の包括的な開発基盤として発展しているケースもありますが、これについてはまた別途紹介したいと思います。
@gilbite a.k.a. イケ☆メン
KLabのゲーム開発・運用で培われた技術や挑戦とそのノウハウを発信します。
合わせて読みたい
KLabのゲーム開発・運用で培われた技術や挑戦とそのノウハウを発信します。