- 2013-12-16 (月) 17:00
- Advent Calendar 2013 | Docker | PHP
Shin x blog Advent Calendar 2013 の 16 日目です。
最近話題の Docker 色々と触っています。
触ってみる中で、普段の開発現場でどのような用途に使えそうなのかを考えています。こうだ!という結論が出ているわけではないのですが、一度書き出してみます。
前提
- Webシステムの開発現場を想定しています。
- 言語は普段使っている PHP ですが、内容にはあまり関係無いです。
- 開発機には Mac OSX を使っています。
検証環境(サンドボックス)
まず一番に思いつくのが、検証環境としての利用です。Docker を使えば、OS のみがインストールされている状態のコンテナを手軽に作成できるので、そこでミドルウェアのインストール、設定などを自由に行い、検証が済んだら、破棄します。
OSX 環境では Docker は動かないので、Vagrant + VirtualBox 上の VM に Linux 環境を構築して、その上で、Docker を動かします。
Docker のインストールは、Vagrantfile に仕込んでおき、vagrant up すれば、Docker デーモンが起動している状態にします。
SSH でログインして、docker run してコンテナを起動するイメージです。dockerui を VM or docker コンテナで動かして、OSX のブラウザからコンテナする方法もありますね。
例えば、先日のエントリでは、下記のコマンドで CentOS の Docker コンテナを使って、コンテナ作成、yum インストール、コンテナ破棄を繰り返しました。vagrant up & destory を繰り返すより、圧倒的に速いので、かなり効率が良いです。
$ sudo docker run -i -t centos /bin/bash # yum -y install php # exit
開発環境
Web システムの開発環境としての利用です。
Vagrant と用途としては似ており、環境構築の自動化、VCS でのバージョン管理、共有などが可能です。
OSX で開発を行う場合、開発ツールは OSX のものを使い、コードの実行をコンテナ内にしたいと思うのですが、ファイル共有は Vagrant の synced_folder と docker run の -v オプションを、OSX のブラウザからコンテナ内へのアクセス(通信)も Vagrant の ポートフォワーディングや private_network と docker run の -p オプションを組み合わせることで可能です。
ただ、実用では考えないといけない点が、2 点あります。
まず、プロジェクトごとに VM を作って、そこに Docker コンテナを作るか、ひとつの VM に複数プロジェクトの Docker コンテナを集積させるかについてです。
前者の場合は、従来プロジェクトごとに Vagrantfile を作っていたのと同じ感覚で Dockerfile を管理できるので管理は楽です。こうなると VM は Docker を動かすだけのプラットフォームに過ぎないようになります。つまり VM の OS は Docker さえ動けばどれでも良く、CoreOS などの軽量な OS を使う方向に進みそうです。ただ、プロジェクトごとに VM が起動するので、Vagrant で VM を作って、プロビジョニングするのとそれほど変わらないといえば、そうかもしれません。
後者の場合、一つの VM 上でプロジェクト毎の Docker コンテナを起動するので、OSX 上で動かす VM は一つだけで良くなります。モバイルなどバッテリ駆動での作業を考えると、起動する VM は少ない方が良さそうです。また、一つの VM を共有するので、Docker イメージのキャッシュを生かすことができます。いつも同じイメージをベースにするのなら、キャシュ済イメージからコンテナを生成できるので、高速に起動することができます。
次に、これは開発環境に限らずですが、Web システムを構成するコンポーネント(Web / App / DB等)をそれぞれ独立したコンテナにするか、一つのコンテナに入れてしまうかです。
前者の場合、それぞれのコンテナを部品として扱いやすく、再利用性は高まります。docker run を複数回実行する必要はありますが、Vagrantfile に記述しておけば良いので、それはあまり問題にならないです。本番環境にて、各コンポーネントを分離している場合や、外部サービス(RDSなど)を利用する場合は、そもそも別ノードにあるコンポーネントと協調して動くことが想定されているので、この方がより稼働環境に近くなるとも言えます。
ただ、上述したように、もし一つの VM で複数プロジェクトのコンテナを動かす場合、どのプロジェクトのコンテナなのかを判別して、起動ポートなども調整する必要があり、このあたりの管理が煩雑になりそうです。
後者の場合、プロジェクトで利用するコンポーネントを全て一つのコンテナに収容するので、見た目として分かりやすいです。一つの Dockerfile で収まるので、コンテナ構築のコードも見通しは良いです。(ただ複数コンポーネントをプロビジョニングするコードが内包するので複雑になりがちです。各コンポーネンのコードは別ファイルにするなどが必要。)ただ、本番環境では、多くの場合、何でも入りコンテナ一つで動かすのではなく、少なくとも DB は別ノードになるなど分離することが多いので、そうなるとアプリケーション以外のコンポーネントは不要になるかもしれません。
まだ全てが Docker コンテナで完結するわけではないので、開発環境と割り切れば、一つのコンテナにまとめるのは悪くないと思います。
CI 環境
CI において、テストを実行する環境としての利用です。
ここでも Docker コンテナの起動の速さは生きてきますね。これも構成の悩みは、開発環境と同じですが、いずれにせよ、 コンテナ構築からテスト実行、コンテナ破棄まで自動実行するので、開発環境に合わせた構成で良いと思います。
できれば、CI でテスト実行したコンテナを、そのまま本番環境へデプロイできたりすると美しいです。
コンテナビルド、テスト実行、テスト完了なら、ビルドしたコンテナをそのまま本番環境へデプロイという流れです。CI サーバがアプリケーションを生成して出荷する工場になるイメージですね。
本番環境
CI 環境でも書きましたが、Docker コンテナを利用している PaaS はありますが、Docker コンテナをそのままデプロイする環境というのはまだ無いように思います。(あったら教えて下さいm(_ _)m)
CI 環境で構築したコンテナをどうデプロイするかですが、直接コンテナを送信するのがまず一つです。ただ、できれば docker push で、コンテナリポジトリに push するとそれが本番環境へデプロイされたりすると良いですね。現在は index.docker.io へ push するのみで、さらに index.docker.io では公開コンテナした置けないのですが、外部リポジトリに push できたり、index.docker.io にプライベートなコンテナを置けたりするようになると利便性が上がります。
今のところは、Dockerfile を送信して、本番環境でコンテナをビルドするという形が現実的ですね。
さいごに
Docker をどう使うかを考えてみました。といってもまだアイデアレベルなのですが、試しながら、もやもやと考えている日々です。
まだ模索中なので、こうしてるよ、こうした方が良いよなどアドバイスあれば、教えて頂けると嬉しいです 😀
これから触ってみようという方は、入り口として、検証を行うサンドボックスとして使ってみるのがおすすめです。