Docker 1.12のビルトイン・オーケストレーションを(Macで)使ってみる

Dockerに新しく追加されたビルトインのオーケストレーションを試してみます。

> このポストを書き終わった時点で、[docker v1.12のオーケストレーション機能をマルチホストで試すよ on さくらのクラウド](http://qiita.com/yamamoto-febc/items/afc7143e609c170140e6)を見つけました。
> 
> すごくよく書かれているので少し気が引けますが、僕のポストはMacのローカルで試してみる、という点で若干の違いがあるのでこのままポストします。


手順の流れは下記の通りです。

1. Swarm Managerノードを作って、Swarm Workerノードを２つ追加する。
2. 試しにnginxのコンテナを作る。
3. nginxのレプリカを複数作ってスケールアップする。
4. 試しにレプリカをいくつか削除して挙動を確認する。
5. 試しにWorkerノードを１つ削除して挙動を確認する。

## ひとまずDockerを1.12にアップデートする

手持ちの環境がMac OS Xなので、Mac OS XにDocker for Macがインストールされているのを前提に話を進めていきます。まずは、Docker for Macをアップデートしてバージョンが`1.12.0-rc2`になっていることを確認します。

```
$ docker --version
Docker version 1.12.0-rc2, build 906eacd, experimental
```

## ３つのDockerマシン、manager1, worker1, worker2を作る

```
# manager1を作る
$ docker-machine create --driver virtualbox manager1

# worker1を作る
$ docker-machine create --driver virtualbox worker1

# worker2を作る
$ docker-machine create --driver virtualbox worker2

# 確認する
$ docker-machine ls
NAME       ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
manager1   *        virtualbox   Running   tcp://192.168.99.100:2376           v1.12.0-rc2
worker1    -        virtualbox   Running   tcp://192.168.99.101:2376           v1.12.0-rc2
worker2    -        virtualbox   Running   tcp://192.168.99.102:2376           v1.12.0-rc2
```

この先は下記の通りマシンとIPアドレスが対応していることを前提に話を進めていきます。

| Machine  | IP Address     |
|:-------- |:-------------- |
| manager1 | 192.168.99.100 |
| worker1  | 192.168.99.101 |
| worker2  | 192.168.99.102 |

## Swarm Managerを作る

```
$ eval $(docker-machine env manager1)
$ docker swarm init --listen-addr 192.168.99.100:2377

$ docker info|egrep '^Swarm| IsManager'
Swarm: active
 IsManager: Yes
```

## Workerを追加する

```
# worker1を作る
$ eval $(docker-machine env worker1)
$ docker swarm join 192.168.99.100:2377
$ docker info|egrep '^Swarm| IsManager'
Swarm: active
 IsManager: No

# worker2を作る
$ eval $(docker-machine env worker2)
$ docker swarm join 192.168.99.100:2377
$ docker info|egrep '^Swarm| IsManager'
Swarm: active
  IsManager: No

# 確認する
$ eval $(docker-machine env manager1)
$ docker node ls
ID                           NAME      MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
0ra8kxzmb58pe6ft5va64w7ua *  manager1  Accepted    Ready   Active        Leader
5gv3ybyzn9m8b7tc6wizyjhix    worker2   Accepted    Ready   Active
bom2mr6g2lej017m4v8fou0eu    worker1   Accepted    Ready   Active
```

## 試しにnginxサービスを作る

```
# manager1の環境を準備する
$ eval $(docker-machine env manager1)

# テスト用のネットワークを作る
$ docker network create -d overlay test_net

# nginxサービスを作る
$ docker service create --name nginx --replicas 1 --network test_net -p 80:80/tcp nginx

# nginxサービスのタスクを確認する
$ docker service tasks nginx
ID                         NAME     SERVICE  IMAGE  LAST STATE          DESIRED STATE  NODE
2rnlb559hs612vp1f5ntl46kh  nginx.1  nginx    nginx  Running 50 seconds  Running        manager1
```

nginxイメージのダウンロードに少々時間がかかりますが、`LAST STATE`が`Preparing...`から`Running...`に変わったらブラウザで`http://192.168.99.100/`を開いて **Welcome to nginx!** のメッセージが見れることを確認します。

## レプリカを追加する

```
# レプリカを５つにする
$ docker service scale nginx=5

# 確認する
$ docker service tasks nginx
ID                         NAME     SERVICE  IMAGE  LAST STATE          DESIRED STATE  NODE
2rnlb559hs612vp1f5ntl46kh  nginx.1  nginx    nginx  Running 12 minutes  Running        manager1
cck9rmwa3mfelzykktlhwsoa2  nginx.2  nginx    nginx  Running 5 seconds   Running        manager1
dslg4jbsii0q7b5ztjtljjkik  nginx.3  nginx    nginx  Running 5 seconds   Running        worker2
9g37ap7xh7132nxf4nreh0afl  nginx.4  nginx    nginx  Running 5 seconds   Running        worker1
c28qiurspqxuqoze01winmwgt  nginx.5  nginx    nginx  Running 5 seconds   Running        worker1
```

## 試しにmanager1にあるレプリカを削除してみる

```
# 無理やりmanager1上にあるレプリカを削除してみます
$ docker ps -qa|xargs docker rm -f
```

何が起こるかというと、`manager1`上のコンテナが消えたことをDocker Swarmが検知してくれるらしく、減った分を自動的に再作成してくれます。便利ですね。

```
# しばらく待ってからレプリカの数が減っていないことを確認する
$ docker service tasks nginx
ID                         NAME     SERVICE  IMAGE  LAST STATE          DESIRED STATE  NODE
6n9h53h6326ef5lhfo7nzc5a3  nginx.1  nginx    nginx  Running 9 seconds   Running        manager1
4pt5qy4vhedyhnww1yrtw0epz  nginx.2  nginx    nginx  Running 10 seconds  Running        worker2
dslg4jbsii0q7b5ztjtljjkik  nginx.3  nginx    nginx  Running 5 minutes   Running        worker2
9g37ap7xh7132nxf4nreh0afl  nginx.4  nginx    nginx  Running 5 minutes   Running        worker1
c28qiurspqxuqoze01winmwgt  nginx.5  nginx    nginx  Running 5 minutes   Running        worker1
```

## 試しにworker2を削除してみる

```
# worker2を削除する
docker-machine rm worker2

# しばらく待って、レプリカの数を確認してみる
docker service tasks nginx
ID                         NAME     SERVICE  IMAGE  LAST STATE          DESIRED STATE  NODE
760crpv5j1gwcxtw6j2cwpjj7  nginx.1  nginx    nginx  Running 14 seconds  Running        worker1
b9uigex1dlfp0932xqgn26c8i  nginx.2  nginx    nginx  Running 14 seconds  Running        worker1
7j0qfo99l29sw9rkv0ud16idm  nginx.3  nginx    nginx  Running 48 seconds  Running        manager1
erwcg6nz50mkfgj1xcl8gzw7a  nginx.4  nginx    nginx  Running 48 seconds  Running        manager1
ckfluns4d0ptwlphz8zlof6cq  nginx.5  nginx    nginx  Running 48 seconds  Running        worker1
```

## 片付ける

```
docker service rm nginx
docker-machine rm manager1 worker1
```

## まとめ

- Swarmの構築が驚くほど簡単になっていて、今後はマルチノードがデフォルト化していくように思えます。
- サービスという新しい概念が導入されて、`docker ps`ではswarm全体のコンテナは見えません。今後は`docker run`や`docker ps`はカスタム・イメージの準備とデバッグ以外では使わなくなるかもしれませんね。
- 今のところ`docker service create`にはvolumeをマウントするオプションがなさそうです。（* 後でもう少し調べてみます。）

## 参考にしたリンク
- [Getting started with swarm mode](https://docs.docker.com/engine/swarm/swarm-tutorial/)