Docker Swarm を使ってマルチホスト環境下で Hello World コンテナを動かす


<img src="https://qiita-image-store.s3.amazonaws.com/0/20833/d1ba2dde-e806-d256-b863-a07dbc84e5f6.png" height=200px>

## 概要
Docker公式オーケストレーションツールの 1 つ Docker Swarm を使って複数ホストにまたがる Docker 環境下で hello world を出力するコンテナを走らせてみるという話

## Hello World
### Docker ホストの用意
3 台の Docker ホスト `core-01`, `core-02`, `core-03` を用意する。

* 全台 `2375` ポートから Docker Remote API が利用可能
* 全台の Docker バージョンが 1.4.0 以上かつ同じである

```
core@core-01 ~ $ docker -v
Docker version 1.5.0, build a8a31ef-dirty

core@core-02 ~ $ docker -v
Docker version 1.5.0, build a8a31ef-dirty

core@core-03 ~ $ docker -v
Docker version 1.5.0, build a8a31ef-dirty
```

### Swarm のインストール
`swarm` イメージを pull してくる

```
core@core-01 ~ $ docker pull swarm:latest

core@core-02 ~ $ docker pull swarm:latest

core@core-03 ~ $ docker pull swarm:latest
```

### クラスタを作成
クラスタを作る。どのホストでも良いので `swarm create` コマンドを実行

```
# at core-01
core@core-01 ~ $ docker run --rm swarm create
129c52f89e17cc99bbcb4126f7906d9a
```

### Swarm エージェントの起動

全ホストで、swarm エージェントを起動する。

```bash
# NODE_IP は swarm manager がアクセス可能ならば Public でも Private でも良い
$ docker run \
    -d \
    swarm \
    join \
      --addr=<NODE_IP:2375> \
      token://<CLUSTER_ID>
```

```bash
core@core-01 ~ $ docker run 
  -d \
  swarm \
  join \
    --addr=172.17.8.102:2375 \
    token://129c52f89e17cc99bbcb4126f7906d9a
f7905da5377523b349c502c3aa2d8a66ade19896bd9da84115220d325a4deb24

core@core-02 ~ $ docker run 
  -d \
  swarm \
  join \
    --addr=172.17.8.101:2375 \
    token://129c52f89e17cc99bbcb4126f7906d9a
1f9d34a98272a4482e6923c37e045435bc9d3d61c520613007e6017a32b7d708

core@core-03 ~ $ docker run 
  -d \
  swarm \
  join \
    --addr=172.17.8.103:2375 \
    token://129c52f89e17cc99bbcb4126f7906d9a
9f95ea43ba7071e8d8cb0039c1f39439c232bed10abd035d1236f24d51ebb212
```

### Swarm マネージャを起動

どのホストでも良いので swarm マネージャを立てる。

```
$ docker run \
    -d \
    -p <SWARM_PORT>:2375 \
    swarm \
    manage \
      token://<cluster_id>
```

```bash
core@core-01 ~ $ docker run \
  -d \
  -p 2377:2375 \
  swarm \
  manage \
    token://129c52f89e17cc99bbcb4126f7906d9a
69f63a903c27da19a9d13f48cacce9a1d733a3bef2526eab8daaad63055b5807
```

これでクラスタ環境ができた。

### クラスタリングされた Docker を使う

既存の Docker API 互換の API を提供するのでこれまで通りの `docker` コマンドが実行できる。

```bash
core@core-01 ~ $ docker -H tcp://localhost:2377 info
Containers: 4
Nodes: 3
 core-03: 172.17.8.103:2375
  └ Containers: 1
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 998 MiB
 core-01: 172.17.8.101:2375
  └ Containers: 2
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 998 MiB
 core-02: 172.17.8.102:2375
  └ Containers: 1
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 998 MiB
```

Hello World

```
# クラスタ内のどこかで hello world コンテナを走らせる
core@core-01 ~ $ docker -H tcp://localhost:2377 run -i busybox:latest echo hello world
hello world
```

クラスタワイドに `ps`

```bash
core@core-01 ~ $ docker -H tcp://localhost:2377 ps -a
CONTAINER ID        IMAGE                       COMMAND                CREATED             STATUS                              PORTS                         NAMES
a116c414076e        busybox:buildroot-2014.02   "echo hello world"     15 seconds ago      Exited (0) Less than a second ago                                 core-03/condescending_hopper
69f63a903c27        swarm:latest                "/swarm manage token   5 minutes ago       Up 5 minutes                        172.17.8.101:2377->2375/tcp   core-01/grave_turing
9f95ea43ba70        swarm:latest                "/swarm join --addr=   9 minutes ago       Up 9 minutes                        2375/tcp                      core-03/trusting_colden
1f9d34a98272        swarm:latest                "/swarm join --addr=   9 minutes ago       Up 9 minutes                        2375/tcp                      core-02/focused_goodall
f7905da53775        swarm:latest                "/swarm join --addr=   12 minutes ago      Up 11 minutes                       2375/tcp                      core-01/grave_wozniak
```

クラスタ内の hello world コンテナを削除

```
core@core-01 ~ $ docker -H tcp://localhost:2377 rm a116c414076e
```

Hello World と出力しつづけるコンテナを走らせてみる

```bash
core@core-01 ~ $ docker -H tcp://localhost:2377 run \
  -d \
  --name hello \
  busybox:latest \
  /bin/sh -c "while true; do echo hello world; sleep 1; done"
347de1fa81d97aa45451353efbd9a08e7f8f800fe4590bdeefec1d91c6c1edf5
```

`logs`

```
core@core-01 ~ $ docker -H tcp://localhost:2377 logs -f hello
hello world
hello world
hello world
hello world
hello world
```

コンテナ名はクラスタ内で一意になるので、同じ名前のコンテナを起動させようとするとエラー。

```
core@core-01 ~ $ docker -H tcp://localhost:2377 run -d --name hello busybox:latest echo hello
FATA[0000] Error response from daemon: Conflict, The name hello is already assigned to 347de1fa81d97aa45451353efbd9a08e7f8f800fe4590bdeefec1d91c6c1edf5. You have to delete (or rename) that container to be able to assign hello to a container again.
```

クラスタワイドのイメージ一覧。ホストごとに見たい気もするのでちょっと残念な感じ？

```
core@core-01 ~ $ docker -H tcp://localhost:2377 images | grep busybox | sort
busybox                                      latest                4986bf8c1536        8 weeks ago         2.43 MB
busybox                                      latest                4986bf8c1536        8 weeks ago         2.43 MB

# pull はできないもよう
core@core-01 ~ $ docker -H tcp://localhost:2377 pull busybox
FATA[0000] Error: Not supported in clustering mode.
```

クラスタ内のマシンリストを見てみる。

```bash
core@core-01 ~ $ docker run --rm swarm list token://129c52f89e17cc99bbcb4126f7906d9a
172.17.8.102:2375
172.17.8.101:2375
172.17.8.103:2375
```

## REF

* [公式ドキュメント](https://docs.docker.com/swarm/)
* [Docker Swarm リファレンス](http://qiita.com/spesnova/items/f4b5f7ee57c9271c9dbd)