Vagrant を用いると Docker 関連の作業がはかどります。Vagrant と Docker は相容れない関係にあるのではなく、実は親和性が高くなるように作られています。Vagrant の基本については公式ドキュメント「GETTING STARTED」などをご参照ください。また以下の内容を理解するにあたり Docker のイメージをつかむには公式サイトのチュートリアルが有用です。本ページの内容を越えるものについては公式ドキュメントをご参照ください。Docker チートシートはこちらです
Vagrant と Docker の関係には二種類あります。Docker というものの概念は一定で、それに対して Vagrant がどう関わるかによる分類です。
Vagrant は up 時に通常通り VirtualBox などの VM を起動します。Vagrant は更にその VM に docker コマンドを自動でインストールします。そして Vagrantfile で指定しておいた Docker の image を pull または build します。更にその image を run してコンテナを作成する設定まで Vagrantfile に記述することができます。公式ドキュメントはこちらです。
Vagrant は既定では VirtualBox を provider として利用して VM を起動します。しかしながら、実は up 時に任意の provider を指定できます。Docker を指定するためには以下のようにします。
$ vagrant up --provider=docker
注意すべきは、Docker Provider で up した場合に VM は起動しないということです。つまり Vagrantfile では config.vm.box を指定しません。代わりに、どの Docker image を用いてコンテナを作成するかを指定する必要があります。Vagrant は up 時に Vagrantfile で指定された image をホストマシン上で直接 build または pull して run することでコンテナを作成します。Vagrant ssh でログインする対象は VM ではなく run して作成したコンテナです。
ホストマシンが Windows の場合 docker が動作せず、したがって Vagrantfile で指定された image を pull/build することも run することもできません。そのため Vagrant は自動で軽量の VM をホストマシン上にまず起動し docker コマンドをインストールします。その VM 上で Vagrantfile で指定された image を build/bull および run してコンテナを用意します。この軽量の VM 起動および docker のインストールは Vagrant がすべて自動で検知して実行するため、ユーザが Vagrantfile に明記することはありません。同じ Vagrantfile を Linux と Windows で使用できます。Provider としての Docker に関する公式ドキュメントはこちらです。
上述の通り Vagrant によって Docker を扱うことが可能です。Windows などで Docker を Provider として使用する際には必要に応じて軽量の VM を VirtualBox などで起動します。これは Boot2Docker という Docker インストーラと似ているため、混同しないように注意してください。Windows および Mac OS X で Boot2Docker を使用すると軽量の VM が VirtualBox などを利用して起動して Docker を利用できるように初期設定がなされます。Windows および Mac OS X では直接 Docker が動作しないため VM を介する仕組みとなっています。どことなく Vagrant で Docker を操作する際の挙動と似ていますので注意してください。
Chef は自動化を提供し Docker は抽象化を提供します。こちらのページで触れた Chef はプロビジョニング機能を提供します。しかしながら、必ずしも汎用的な記述がなされている保証がなく特定の OS や CPU に特化したレシピが作成できてしまいます。これは、開発環境には適用できて本番環境には適用できない、という事態を招きます。それに対して Docker ではコンテナがどのような環境でも Docker エンジンさえあれば動作することが保証されています。その代わり、シェルスクリプトのような簡単な手続きを記述することはできますが、自動化としての機能は Chef ほど充実していません。Chef によって Docker をインストールするためのレシピに関する記述はこちらです。
「Dockerizing a Node.js Web App」を Vagrant で再現します。ディレクトリ構成は以下の通りです。
$ tree .
.
├── Dockerfile
├── index.js
├── package.json
└── Vagrantfile
全体としては最後に示す通りです。その前にいくつかポイントを示します。
windows:8080 → vagrant:49160 → docker:8080
config.vm.network "forwarded_port", guest: 49160, host: 8080
Windows の 8080 ポートを仮想マシンの 49160 ポートに転送するための記述です。
d.run "qoosky/centos-node-hello", args: "-p 49160:8080 -d"
仮想マシンの 49160 ポートを Docker コンテナの 8080 ポートに転送するための記述です。
config.vm.provision "shell", inline: "yum update -y device-mapper-libs"
chef/centos-6.5 という Vagrant の BOX に Docker をインストールするためには device-mapper-libs をアップデートしておく必要があるためです。こちらのページを参考にしました。この記述がない場合は以下のエラーが出ます。
Cannot connect to the Docker daemon. Is 'docker -d' running on this host?
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "chef/centos-6.5"
config.vm.network "forwarded_port", guest: 49160, host: 8080
config.vm.provision "shell", inline: "yum update -y device-mapper-libs"
config.vm.provision "docker" do |d|
d.build_image "/vagrant", args: "-t qoosky/centos-node-hello"
d.run "qoosky/centos-node-hello", args: "-p 49160:8080 -d"
end
end
なお 2015/02/11 現在 Docker は 64bit のホスト OS にしか対応していません。Vagrantfile で指定する BOX は 64bit である必要があります。例えば "chef/centos-6.5-i386" を指定すると Docker をインストールできません。"chef/centos-6.5" を指定してください。お使いの PC によっては BIOS 設定で仮想化技術を有効にする必要があります。
基本となるイメージ centos:centos6 に Express.js などをインストールします。
FROM centos:centos6
# Enable EPEL for Node.js
RUN rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
# Install Node.js and npm
RUN yum install -y npm
# Bundle app source
COPY package.json index.js /src/
# Install app dependencies
RUN cd /src; npm install
EXPOSE 8080
CMD ["node", "/src/index.js"]
npm install で Express.js をインストールするためのファイルです。
{
"name": "docker-centos-hello",
"private": true,
"version": "0.0.1",
"description": "Node.js Hello world app on CentOS using docker",
"author": "Daniel Gasienica <daniel@gasienica.ch>",
"dependencies": {
"express": "3.2.4"
}
}
Hello world と表示するだけの Express.js アプリケーションです。
var express = require('express');
// Constants
var PORT = 8080;
// App
var app = express();
app.get('/', function (req, res) {
res.send('Hello world\n');
});
app.listen(PORT);
console.log('Running on http://localhost:' + PORT);
以下のコマンドで chef/centos-6.5 の起動および Docker のインストール、イメージのビルド、コンテナの作成まで自動で実行されます。
windows$ vagrant up
例えば以下のコマンドで Vagrant VM に SSH します。
windows$ vagrant ssh
あるいは以下のコマンドで確認した情報をもとに RLogin などのクライアントを使用してもよいです。
windows$ vagrant ssh-config
ログインしたら以下のコマンドでイメージがビルドされたことを確認できます。
vagrant$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
qoosky/centos-node-hello latest a05c84307fab 53 minutes ago 433.8 MB
イメージが run されて作成されたコンテナは以下のコマンドで確認します。
vagrant$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3163e5cc3e55 qoosky/centos-node-hello:latest "node /src/index.js" 40 minutes ago Up 35 minutes 0.0.0.0:49160->8080/tcp qoosky-centos-node-hello
コンテナのログを確認してみましょう。
vagrant$ docker logs qoosky-centos-node-hello
Running on http://localhost:8080
HTTP リクエストを 49160 に対して発行してみます。正常に動作しているようです。
vagrant$ curl -i localhost:49160
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 12
Date: Sat, 07 Feb 2015 11:01:51 GMT
Connection: keep-alive
Hello world
最後に Windows のブラウザで http://127.0.0.1:8080/ にアクセスしてみます。
DockerHub の httpdイメージ を pull して run する Vagrantfile の例を示します。
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.provider "docker" do |d|
d.image = "httpd"
end
end
以下のコマンドでコンテナを作成します。
$ vagrant up --provider=docker
ログを取得してみましょう。
$ vagrant docker-logs
==> default: AH00558: httpd: Could not reliably determine the server's
fully qualified domain name, using 172.17.0.4. Set the 'ServerName'
directive globally to suppress this message
==> default: AH00558: httpd: Could not reliably determine the server's
fully qualified domain name, using 172.17.0.4. Set the 'ServerName'
directive globally to suppress this message
==> default: [Sat Feb 07 07:22:02.164451 2015] [mpm_event:notice]
[pid 1:tid 139768255600512] AH00489: Apache/2.4.12 (Unix) configured
-- resuming normal operations