dnsdock の Docker イメージを小さくする - Qiita でご紹介した dnsdock を使って何か出来ないかと考えていたのですが、同時に1サイト(コンテナ)しか起動できない Wocker をサンプルに、「複数コンテナを立ち上げて自動的に名前解決してローカルマシンからアクセス出来るようにする」ことを思いつきました。
レシピは大きく分けて3つ。
- Wocker にパッチを当てて複数のコンテナを起動出来るようにする。
- dnsdock コンテナを立ち上げる。
- ローカルマシンの DNS Resolver とルーティングの設定をする。
1.に関しては Wocker を取り上げていますが、dnsdock の利用は Wocker でなくてもどんなコンテナにも応用可能です。
3.に関しては Mac OSX を前提としていますが、同様の設定が Windows や他の OS でも可能であれば同じようなことが出来るはずです。
下記の解説は一部簡略化して手入力で行っていますが、完全版は
https://github.com/ailispaw/wocker/tree/wocker-multi
を参照して下さい。下記の作業は全て自動的に行われます。
(3.の設定には vagrant-triggers
プラグインが必要になります)
Wocker について
Docker-based rapid development environment of WordPress
http://wckr.github.io/
Wocker は、Docker を使って WordPress の開発環境を高速に構築するツールです。
その Docker ホスト VM(wocker VM)は Vagrant を使って起動され、そのベースとなる box に私が開発している Docker ホスト用軽量 OS を採用して頂いた関係で Watch させて頂いております。
VirtualBox と Vagrant がインストールされていれば、
$ git clone https://github.com/wckr/wocker.git && cd wocker
$ vagrant up
$ echo "10.0.23.16 wocker.dev" | sudo tee -a /etc/hosts
$ open http://wocker.dev
だけで、ローカルマシンのブラウザでサイトが確認出来るようになります。
(vagrant-hostsupdater
プラグインがインストールされていれば、/etc/hosts
の設定は自動的に行われます)
サイトのコードはローカルマシンの ./data
ディレクトリ内に保存されて、VM/コンテナと同期されているので、ローカルでそのまま開発が出来るようになっています。
1.Wocker にパッチを当てる
wocker
スクリプトへのパッチ
Wocker の内部では wocker
というスクリプトが docker run
を使って WordPress コンテナを起動しているのですが、オプションに -p 80:80 -p 3306:3306
が指定されており、wocker VM のポートを専有してしまうので、同じコンテナを同時に複数起動することは出来ません。
これを削除してしまいます。
$ vagrant ssh
Welcome to DockerRoot version 1.2.11, Docker version 1.9.1, build 66c06d0-stripped
wocker ~ $ sed -i 's/-p 80:80 -p 3306:3306//g' /opt/bin/wocker
逆に、これによって VM の IP アドレスである 10.0.23.16
(wocker.dev) ではアクセス出来なくなってしまいます。そこで、dnsdock
の出番となります。
wocker/wocker
Docker イメージ/ WordPress コンテナへのパッチ
WordPress コンテナのベースとなるイメージ wocker/wocker
には、既に WordPress と共に、必要なツールや環境設定が予めパッケージングされています。前提としてサイトの URL が http://wocker.dev
に固定されている為、このままでは、同時に起動出来たとしても、異なるサブドメインを使って複数のサイトにアクセスしても表示がうまくいきません。
これを各コンテナの起動直後に docker exec
を使って変更してしまいます。
wocker ~ $ wocker run --name <container-name>
wocker ~ $ docker exec <container-name> wp option --allow-root update siteurl http://<container-name>.wocker.dev
wocker ~ $ docker exec <container-name> wp option --allow-root update home http://<container-name>.wocker.dev
2.dnsdock コンテナを起動する
wocker ~ $ docker run -d --name dnsdock -v /var/run/docker.sock:/var/run/docker.sock -p 53:53/udp ailispaw/dnsdock /dnsdock -domain=dev
-
/var/run/docker.sock
をマウントすることにより、ホスト VM 上の Docker リソースにアクセス出来るようになり、自動的にコンテナを認識して DNS を設定します。 -
53:53/udp
で DNS ポートをホスト VM にマッピングすることにより、ホスト及び外部から10.0.23.16
で DNS サーバーにアクセス出来るようになります。 - 最後の
-domain=dev
はドメイン名を.dev
にするオプションで、省略すると.docker
になります。
これらの設定から、dnsdock は <container-name>.<image-name>.<domain>
で特定のコンテナにアクセス出来るように DNS を自動的に設定します。
例えば、Wocker の vagrant up
直後は wocker/wocker
イメージを使って wocker
という名前のコンテナが自動的に起動されるようになっているので、そのコンテナにはwocker.wocker.dev
でアクセスすることになります。
wocker ~ $ nslookup wocker.wocker.dev 10.0.23.16
Server: 10.0.23.16
Address 1: 10.0.23.16
Name: wocker.wocker.dev
Address 1: 172.17.0.3 wocker.dev
wocker ~ $ exit
logout
$ nslookup wocker.wocker.dev 10.0.23.16
Server: 10.0.23.16
Address: 10.0.23.16#53
Non-authoritative answer:
Name: wocker.wocker.dev
Address: 172.17.0.3
3.ローカルマシンの DNS Resolver とルーティングの設定をする
上記で下準備が出来ました。
残りはローカルマシン側の設定です。
特定のドメインに対して DNS Resolver を指定する
Mac OSX の場合 /etc/resolver
ディレクトリにドメイン名のファイルを作り、その中に DNS サーバーのアドレスを書き込むことによって、その特定のドメイン名のアドレス解決はその DNS サーバーを使用するようになります。
$ sudo mkdir -p /etc/resolver
$ echo "nameserver 10.0.23.16" | sudo tee /etc/resolver/dev
コンテナのアドレスを VM にルーティングする
この場合、具体的には、Docker のデフォルトのコンテナのアドレス・レンジ 172.17.0.1/16
を 10.0.23.16
にルーティングすることになります。
$ sudo route -n add -net 172.17.0.0 10.0.23.16
以上で、ローカルマシンのブラウザから http://wocker.wocker.dev/
にアクセス出来るようになります。
複数のコンテナの起動
WordPress (wocker/wocker)コンテナを別名で起動して上記1.のように docker exec
でパッチを当てるとその名前でブラウザからアクセス出来るようになります。
https://github.com/ailispaw/wocker/tree/wocker-multi
では wocker-multi
というスクリプトを用意して、その部分を自動化していますので、
$ vagrant ssh -c "wocker-multi <container-name>"
$ open http://<container-name>.wocker.dev
だけで、そのサイトを見ることが出来ます。
サイトのデータは ./data/<container-name>
に保存されます。
長くなってしまいましたが、
肝心な部分は2.の dnsdock コンテナの起動だけで、コンテナの名前ーアドレス解決が自動的に出来るようになるってところです。
単一の Docker ホスト内に制限はされますが、Wocker にかぎらず、他のコンテナにも応用出来ます。
ローカルの開発には十分有効なのではないでしょうか。
それではまた。