Dockerの構成管理「Fig」で開発環境を整備しよう
Dockerに対する注目がどんどん高まっています。GoogleやMicrosoftもDockerを積極的に採用して自社クラウドサービスに組み込んでいますし、Dockerを使ったコンテナベースのクラウドサービスも増えています。
Dockerでは各コンテナではあまり複雑な構成をせず、1コンテナ1アプリケーションとして、コンテナ間をリンクして使うのがお勧めです。それによってコンテナ間の依存度を下げつつ保守性を維持できるのがメリットになります。
逆にデメリットとしては構成が複雑になるためにアプリケーションをまとめあげ、構成する仕組みが必要になります。今回はそのためのツールとしてリリースされたFigを紹介します。元々Orchard Labsが開発していましたがDocker社に買収され、2014年10月にリリースされたツールになります。Docker本体が買収したとあって、需要は高いツールと言えるでしょう。
Figは開発環境を柔軟に管理、運用するツールになります(開発環境用オーケストレーションツールです)。Linux上またはMac OSX上(boot2docker利用)が想定されているようです。今回はこのFigの使い方を紹介します。なおOSはUbuntu 14.04 LTSを使っています。
Figのインストール
FigはDockerの最新版である1.3以上で動作します。CoreOSや通常のaptなどでインストールできるバージョンは低いので最新版にします。こちらのコマンドを実行します。
$ curl -sSL https://get.docker.io/ubuntu/ | sudo sh $ docker -v Docker version 1.3.1, build 4e9bbfa
Dockerをインストールしたら、設定ファイルを編集した後でサービスとして起動します。
$ cat /etc/default/docker : # DOCKER_OPTSをこのように編集します。 #DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4" (元) # ↓ DOCKER_OPTS="-H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock --dns 8.8.8.8 --dns 8.8.4.4" :
設定を編集したらサービスとして起動し、DOCKER_HOSTを環境変数に設定します。
$ sudo restart docker # Dockerをサービス起動します $ export DOCKER_HOST=tcp://localhost:4243 # DockerのURIを設定します
次にFigのインストールです。次のコマンドでインストールできます。
# curl -L https://github.com/docker/fig/releases/download/1.0.1/fig-`uname -s`-`uname -m` > /usr/local/bin/fig; chmod +x /usr/local/bin/fig
バイナリがGitHubで公開されていますので、それを /usr/local/bin/fig としてコピーしています。なおMac OSX版もあるのですが、こちらはboot2dockerをインストールすれば同梱されるようです。
$ fig --version fig 1.0.1
これで準備は完了です。
Ruby on Rails環境を構築する
まずRuby on Railsの開発環境を構築する例になります。構成としては、Web(Ruby on Rails)とDB(PostgreSQL)という構成になります。
作業用ディレクトリを作成します。
$ mkdir rails $ cd rails
Dockerfileを次の内容で作成します。
$ cat Dockerfile FROM ruby RUN apt-get update -qq && apt-get install -y build-essential libpq-dev RUN mkdir /myapp WORKDIR /myapp ADD Gemfile /myapp/Gemfile RUN bundle install ADD . /myapp
Rubyがあらかじめ入ったコンテナイメージをベースに、aptで必要なものをインストールしています。さらに myapp というディレクトリを作成し、そこにGemfileを入れています。とてもシンプルで、PostgreSQLに関する記述はありません。
次に同じディレクトリにGemfileを作成します。こちらはまず最低限です。
$ cat Gemfile source 'https://rubygems.org' gem 'rails', '4.0.2'
最後に fig.yml を作成します。これがFigが使う構成管理に関する設定ファイルです。
$ cat fig.yml db: image: postgres ports: - "5432" web: build: . command: bundle exec rackup -p 3000 volumes: - .:/myapp ports: - "3000:3000" links: - db
リンクするデータベース(db)のイメージファイルやポート番号、さらにWebアプリケーション(web)の実行コマンドやポート、リンクに関する設定が記述されています。これまでDockerfile内で記述されていたような内容ですが、分離することでfig.ymlが構成管理に関する記述だけにまとめられるようになっています。
ここまでの記述が終わったら、figコマンドを実行します。
$ fig run web rails new . --force --database=postgresql --skip-bundle
fig run というコマンドで指定したコンテナ(ここではweb)に対して任意のコマンドが実行できます。ここでは rails new . --force --database=postgresql --skip-bundle
が実行されると言うことで、Gemfileに記述した内容と同じくRuby on Railsがインストールされます。このときPostgreSQLのコンテナイメージも取得するのでしばらくかかります。
終わると次のようにRailsアプリケーションの基本構成がカレントディレクトリに展開されます。
$ ls app config db fig.yml Gemfile.lock log Rakefile test vendor bin config.ru Dockerfile Gemfile lib public README.rdoc tmp
今後、GemfileやDockerfileをアップデートした際には fig build
コマンドを実行する必要があるようです。
最後にRailsアプリケーションのデータベース設定を編集します。
$ cat config/database.yml : development: adapter: postgresql encoding: unicode database: postgres pool: 5 username: postgres password: host: db
hostがdbと簡単な表記になっているのが特徴です。これでFigで設定しているdbと連携してくれるようになります。
ではRailsアプリケーションを実行します。
$ fig up Recreating rails_db_1... Recreating rails_web_1... Attaching to rails_db_1, rails_web_1 db_1 | LOG: database system was interrupted; last known up at 2014-11-07 08:25:16 UTC db_1 | LOG: database system was not properly shut down; automatic recovery in progress db_1 | LOG: record with zero length at 0/1782A80 db_1 | LOG: redo is not required db_1 | LOG: database system is ready to accept connections db_1 | LOG: autovacuum launcher started web_1 | [2014-11-07 12:42:49] INFO WEBrick 1.3.1 web_1 | [2014-11-07 12:42:49] INFO ruby 2.1.4 (2014-10-27) [x86_64-linux] web_1 | [2014-11-07 12:42:49] INFO WEBrick::HTTPServer#start: pid=1 port=3000
コンソールに入る場合は次のようになります。
$ fig run web rails c Loading development environment (Rails 4.0.2) irb(main):001:0>
figというコマンドを介しているものの、ローカルで開発しているのと変わらないくらいの感覚でDockerが使えるようになるのではないでしょうか。仮想化がされているので開発環境の可搬性があがり、メンテナンスはとてもしやすいでしょう。
WordPressを立ち上げる
次にWordPressをFigを使って立ち上げてみます。
$ mkdir wordpress $ cd wordpress
まず、WordPressをダウンロードして解凍します。
$ curl https://wordpress.org/latest.tar.gz | tar -xvzf -
そうするとwordpressというディレクトリができます。
続いてDockerfile、fig.ymlを作成します。
$ cat Dockerfile FROM orchardup/php5 ADD . /code
$ cat fig.yml web: build: . command: php -S 0.0.0.0:8000 -t /code ports: - "8000:8000" links: - db volumes: - .:/code db: image: orchardup/mysql environment: MYSQL_DATABASE: wordpress
こちらもまたDockerfileはとてもシンプルに保たれていることが分かるかと思います。
そして wordpress/wp-config-sample.phpをベースに設定ファイルを作成します。
define('DB_NAME', 'wordpress'); define('DB_USER', 'root'); define('DB_PASSWORD', ''); define('DB_HOST', "db:3306"); define('DB_CHARSET', 'utf8'); define('DB_COLLATE', '');
データベースの接続情報について編集します。こちらもホスト設定がdb:3306とシンプルなものになっているのが分かるかと思います。
最後にPHPのビルトインWebサーバ用にファイルを作成します。
$ cat router.php <?php $root = $_SERVER['DOCUMENT_ROOT']; chdir($root); $path = '/'.ltrim(parse_url($_SERVER['REQUEST_URI'])['path'],'/'); set_include_path(get_include_path().':'.__DIR__); if(file_exists($root.$path)) { if(is_dir($root.$path) && substr($path,strlen($path) - 1, 1) !== '/') $path = rtrim($path,'/').'/index.php'; if(strpos($path,'.php') === false) return false; else { chdir(dirname($root.$path)); require_once $root.$path; } }else include_once 'index.php';
これで準備は完了です。Figを実行します。初回はイメージをとってくるので時間がかかります。
$ fig up
Dockerfileを使って設定を記述するとはいっても、実際には単体では難しく、別途Shellスクリプトを実行するケースはとても多かったです。さらに複雑化すれば記述内容が増えたり、メンテナンス性が悪くなります。それではDockerの持ち味が活かせなくなるでしょう。
Figは構成を分かりやすくできるほか、例えば
$ fig scale web=2 worker=3
のように実行することでWebというコンテナの数を増やすこともできます。Dockerを使った運用が柔軟になりそうです。開発環境でこういった複数構成を試せるのが良いですね。これまでVagrantで構築していたのをboot2docker + Figにすることで複数のプロジェクトを切り替えたり、多くのVMイメージファイル管理から解放されるのではないでしょうか。
ぜひFigを使って開発、運用負荷を軽減してください!