何周遅れだよって話ではあるけど Docker 使い始めました。
さて、【参考訳】 プロダクションに対応するマルチホスト Docker ネットワーク機能を参考にして試した。みんな「dockerのリンクはとても便利」と絶賛するけどどうも馴染まなかった自分には素晴らしい展開。
まずシングルホストでMySQLノードへと他のノードから接続させるテストをしたのち、マルチホストで同様の動作を試すことに。
動作環境は以下のとおりです。
- MacBook(2015) Mem 8GB
- OS X El Capitan
- virtualbox 5.0.8
メモリが足りない。
<追記>なお、この記事の上位互換の内容が @zembutsu さんによって[書かれている](http://qiita.com/zembutsu/items/4cd756ff8be4be76e5a3)のでより詳細な内容を知りたい場合はそちらを。追記>
Docker Toolboxのインストール
初心者なので公式インストーラを使います。
シングルホストで試す
docker networkを作る
$ docker network create backend
461b41ec193090776948e42bee70b64cdc46dfe59e8206e5bbf0cb49372d9589
必要なイメージを pull する
$ docker pull mysql
$ docker pull centos
DBを作る
db
というホスト名で、backend ネットワークに所属するコンテナを作成する。
$ docker run -d -e MYSQL_ROOT_PASSWORD=mysql --net=backend --name db mysql:5.7
3637731853a41c7c318c0f88d356005e48cf76806f360f0d5df8c217beaa544d
もいっこCentOSを立てて、さっきのDBにアクセスする
同じネットワークに属したホスト同士はホスト名でお互いを解決できる。
ネットワーク名(backend)とホスト名(db)の組み合わせで名前解決できることがわかる。このあたりの動きは自然。なお、/etc/hosts
を見ればわかるが同じネットワークに属しているのでホスト名だけでも解決できる。
$ docker run -it --net=backend centos
[root@1ea2906c98f0 /]# ping db.backend
PING db.backend (172.19.0.2) 56(84) bytes of data.
64 bytes from db (172.19.0.2): icmp_seq=1 ttl=64 time=0.153 ms
64 bytes from db (172.19.0.2): icmp_seq=2 ttl=64 time=0.080 ms
64 bytes from db (172.19.0.2): icmp_seq=3 ttl=64 time=0.085 ms
[root@1ea2906c98f0 /]# yum install -y mysql
....
[root@1ea2906c98f0 /]# mysql --version
mysql Ver 15.1 Distrib 5.5.44-MariaDB, for Linux (x86_64) using readline 5.1
[root@1ea2906c98f0 /]# mysql -h db.backend -uroot -pmysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.9 MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
ちゃんとdb.backend
という名前で MySQL 5.7.9 に接続できた!
[root@1ea2906c98f0 /]# cat /etc/hosts
172.19.0.3 1ea2906c98f0
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.19.0.2 db
172.19.0.2 db.backend
これら名前は /etc/hosts
に書かれている。まあこのあたりは理解できる話。しかし、この状態で mysql のコンテナを落とすと /etc/hosts に書かれた mysql のエントリも消える。 しかも、**新しく同じネットワークにコンテナを起動すると /etc/hosts にエントリが増える。**なんてことだ。やや感動した。
<余談> MySQLサーバの方の /etc/hosts
こうなってた。
# cat /etc/hosts
172.19.0.2 3637731853a4
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
#
centosがいないのはホスト名つけてないからかな。
<余談>作成済みのコンテナを後からネットワークに所属させたり
コンテナ作成時に --net=hogehoge
で指定するだけでなく、connect サブコマンドで後から所属させることができる。
$ docker network connect <コンテナ名> <ネットワーク名>
手元で試した際、-p 80:80
で公開済みの Nginx コンテナを frontend ネットワークに所属させようとしたら、以下のように怒られたので一度ポートのバインド外す必要があったりとかしそう。このあたりは細かく見てない。ごめんなさい。
$ docker network connect frontend nginx_web
Error response from daemon: failed to create endpoint nginx_front on network frontend: Bind for 0.0.0.0:80 failed: port is already allocated
マルチホストで試す
swarm を作る
$ docker run swarm create
=> <SWARM_TOKEN>
このトークンを後から使うのでとっておく。
ところでマルチホストネットワークにはクラスタ設定が必要だ
--cluster-advertise
と--cluster-store
の指定をした Docker Engine が必要である。
To use multi-host networking you need to start your docker engines with --cluster-store and --cluster-advertise as indicated in the docker engine docs
https://docs.docker.com/swarm/networking/
公式のサンプルコードには Consul を起動する手順が書かれている。
ここではとりあえずなので、このまんま Consul用の環境を一個作ってしまう。Consulも使ったことがないが、いいんだ。どう動いているかどうかを細かく理解するのは後回しである。後で見よう。
docker-machine create \
-d virtualbox \
mhl-consul-1
docker $(docker-machine config mhl-consul-1) run -d \
-p "8500:8500" \
-h "consul" \
progrium/consul -server -bootstrap
https://docs.docker.com/swarm/discovery/ このへん見ると クラスタ情報を外部で保持する discovery には consul だけでなく etcd
とか zookeeper
も選択できるみたい。
swarm master を作る
docker-machine create \
-d virtualbox \
--swarm \
--swarm-master \
--swarm-discovery token://${SWARM_TOKEN} \
--engine-opt="cluster-store=consul://$(docker-machine ip mhl-consul-1):8500" \
--engine-opt="cluster-advertise=eth1:0" \
swarm-master
できたらこっちに環境を切り替える。eval $(docker-machine env --swarm swarm-master)
する。
swarm node を作る
$ docker-machine create \
-d virtualbox \
--swarm \
--swarm-discovery token://${SWARM_TOKEN} \
--engine-opt="cluster-store=consul://$(docker-machine ip mhl-consul-1):8500" \
--engine-opt="cluster-advertise=eth1:0" \
swarm-agent-00
$ docker-machine create \
-d virtualbox \
--swarm \
--swarm-discovery token://${SWARM_TOKEN} \
--engine-opt="cluster-store=consul://$(docker-machine ip mhl-consul-1):8500" \
--engine-opt="cluster-advertise=eth1:0" \
swarm-agent-01
確認。
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM
default - virtualbox Running tcp://192.168.99.100:2376
mhl-consul-1 - virtualbox Running tcp://192.168.99.101:2376
swarm-agent-00 - virtualbox Running tcp://192.168.99.103:2376 swarm-master
swarm-agent-01 - virtualbox Running tcp://192.168.99.104:2376 swarm-master
swarm-master - virtualbox Running tcp://192.168.99.102:2376 swarm-master (master)
子供達が増えてた。
swarm-master に接続して状態を見る
swarm-master を普通のDockerエンジンのように扱って接続できる。--swarm
を指定して接続すると、単独ノードではなくクラスタ全体を対象として操作することになる。
$ eval $(docker-machine env --swarm swarm-master)
あとは普通に docker コマンドが使える。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker info
Containers: 4
Images: 3
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 3
swarm-agent-00: 192.168.99.103:2376
└ Containers: 1
└ Reserved CPUs: 0 / 1
└ Reserved Memory: 0 B / 1.021 GiB
└ Labels: executiondriver=native-0.2, kernelversion=4.1.12-boot2docker, operatingsystem=Boot2Docker 1.9.0 (TCL 6.4); master : 16e4a2a - Tue Nov 3 19:49:22 UTC 2015, provider=virtualbox, storagedriver=aufs
swarm-agent-01: 192.168.99.104:2376
└ Containers: 1
└ Reserved CPUs: 0 / 1
└ Reserved Memory: 0 B / 1.021 GiB
└ Labels: executiondriver=native-0.2, kernelversion=4.1.12-boot2docker, operatingsystem=Boot2Docker 1.9.0 (TCL 6.4); master : 16e4a2a - Tue Nov 3 19:49:22 UTC 2015, provider=virtualbox, storagedriver=aufs
swarm-master: 192.168.99.102:2376
└ Containers: 2
└ Reserved CPUs: 0 / 1
└ Reserved Memory: 0 B / 1.021 GiB
└ Labels: executiondriver=native-0.2, kernelversion=4.1.12-boot2docker, operatingsystem=Boot2Docker 1.9.0 (TCL 6.4); master : 16e4a2a - Tue Nov 3 19:49:22 UTC 2015, provider=virtualbox, storagedriver=aufs
CPUs: 3
Total Memory: 3.064 GiB
Name: a1eae869d74b
3ノードが統括されている。
どうでもいいけど 3CPU、Total Memory 3GBはMacBookにはそれなりに深刻…。この他にConsulマシンがいるからね。
ネットワークを作成する
ネットワークを表示してみる。
$ docker network create backend
cf756ea9e77cbabf1e3ba019b4e7afc8b8b4575bd565415e9c304397e23c0664
$ docker network ls
NETWORK ID NAME DRIVER
ded21015a5b2 swarm-master/none null
41558558d9be swarm-master/host host
cf756ea9e77c backend overlay
4cbc614ed481 swarm-agent-01/none null
e9aefb33dfd7 swarm-agent-01/host host
d1435420f650 swarm-master/bridge bridge
01cbc675564a swarm-agent-00/bridge bridge
9ea065803ecc swarm-agent-00/none null
8fbe7735ed4c swarm-agent-00/host host
d69c33adb66c swarm-agent-01/bridge bridge
各ホストごとのネットワークの他に、今作った backend という名のオーバーレイネットワークができてる。
discovery を使わずに各エンジンを作っていると、オーバーレイネットワークの作成ができない。
$ docker network create backend
Error response from daemon: 500 Internal Server Error: failed to parse pool request for address space "GlobalDefault" pool "" subpool "": cannot find address space GlobalDefault (most likely the backing datastore is not configured)
このエラーが出た時は Docker エンジンが cluster-advertise
と cluster-store
の指定なしで作られちゃってる疑惑。docker-machine inspect
で確認するんだ。
上の手順で Consul を立ててなかったりするとこれでこける。
docker pull すると各ノードでダウンロードされる
各ノードでコンテナイメージは持たないとなわけだから、まあそうなるのか。
$ docker pull mysql
Using default tag: latest
swarm-agent-01: Pulling mysql:latest...
swarm-master: Pulling mysql:latest...
swarm-agent-00: Pulling mysql:latest...
$ docker pull centos
Using default tag: latest
swarm-agent-01: Pulling centos:latest... : downloaded
swarm-master: Pulling centos:latest... : downloaded
swarm-agent-00: Pulling centos:latest... : downloaded
全部 virtualbox だと複数並列で pull するので、自宅回線的につらみがある。
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
swarm latest 6b40fe7724bd 3 days ago 15.6 MB
mysql latest fb86ef4dd8b7 8 days ago 359.8 MB
centos latest e9fa5d3a0d0e 3 weeks ago 172.3 MB
swarm だと docker images コマンド叩けないと書かれた記事もあるが、現時点ではそんなこともない模様。
シングルホストの時と同じようにコンテナを作って試す
ネットワーク「backend」に所属させる。
docker run -d -e MYSQL_ROOT_PASSWORD=mysql --net=backend --name db mysql
docker run -it --net=backend --name centos centos
swarm上だと -d
でデーモン起動しないとまずいという記事も見たが、現時点ではフォアグラウンド実行も可能みたい。
別窓でログインして docker ps
打つと、ちゃんと異なるノードで起動しているのがわかる。mysqlは swarm-agent-00、 centosは swarm-agent-01。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6a2a862a4fac centos "/bin/bash" 39 seconds ago Up 38 seconds swarm-agent-01/centos
33358a65ed35 mysql "/entrypoint.sh mysql" 39 minutes ago Up 39 minutes 3306/tcp swarm-agent-00/db
CentOS側でmysql(maria)をインストールして、MySQLノードに接続する。
[root@6a2a862a4fac /]# yum install -y mysql
[root@6a2a862a4fac /]# mysql -uroot -hdb.backend -pmysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.9 MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
でけたー。ちゃんと MySQL5.7.9 につながる。
いい感じに「普通」につながる。
いったんはここまで。