Docker Swarm cluster をTLS 通信でセキュアなクラスタにする

# TLS 認証 
前回の記事で、Docker Swarm の構築についてやっていきました。

[Docker Swarm 入門ハンズオン](http://qiita.com/TsutomuNakamura/items/6124ab7d32a58bc93ac7)

Docker Swarm cluster 内の通信をTLS で行うことができるようになっており、Docker Swarm cluster 間のDocker の通信の機密性を高めることができます。
TLS で使う証明書は自分の手元のコンピュータで作成したCA の署名がついたもので構いませんが、条件としてDocker Swarm manager、Docker Swarm agent(各agent のDocker daemon)、Docker client で使用する証明書はどれも同じCA から署名されていることが条件となっています。
また、Docker Swarm manager の証明書はopenssl の`extendedKeyUsage = clientAuth,serverAuth` オプションで、Docker client の証明書は`extendedKeyUsage = clientAuth` オプションで作成するようにします。

今回は検証目的なので、手っ取り早さを重視して、Docker Swarm manager のDocker ホスト上にCA を作成し、Docker Swarm manager、各Docker Swarm agent のサーバ証明書、Docker Swarm manager のDocker ホストからコマンドを発行するためのクライアント証明書をそれぞれ作成して検証してみることにします。

![Docker_SwarmOnTLS0000.png](https://qiita-image-store.s3.amazonaws.com/0/70152/2c0d18b0-38fe-76be-3fca-0e96665b1707.png)

## 構成 
今回、証明書を使用して認証を行うために証明書のCN(コモンネーム) とアクセスするときに使うFQDN を一致させておく必要があります。
これより先に進む上で混乱を避けるため、ここで一旦、用語とFQDN 及びそれぞれのコンポーネントの用途等について次のように定義して置くものとします。


* 構成
<table><tbody>
  <tr>
    <th> 名前</th>
    <th> IP アドレス</th>
    <th> FQDN</th>
    <th> (Host) OS</th>
    <th> Docker ver</th>
    <th> 備考</th>
  </tr>
  <tr>
    <td> Docker Swarm manager ホスト</td>
    <td> 192.168.1.121</td>
    <td> -</td>
    <td> Ubuntu 15.10</td>
    <td> 1.9.1</td>
    <td> Docker Swarm manager コンテナを起動している物理ホスト/Docker ホスト。今回、クライアントとしてコマンドを送信する作業端末としても利用</td>
  </tr>
  <tr>
    <td> Docker Swarm manager 01 (swmgr01)</td>
    <td> 192.168.1.121</td>
    <td> swmgr01.example.com</td>
    <td> Ubuntu 15.10</td>
    <td> 1.9.1</td>
    <td> Docker Swarm manager コンテナ。このFQDN はDocker Swarm manager ホストの/etc/hosts ファイルに登録しておく</td>
  </tr>
  <tr>
    <td> Docker Swarm manager 01 (swagt01)</td>
    <td> 192.168.1.131</td>
    <td> swagt01.example.com</td>
    <td> Debian jessie</td>
    <td> 1.9.1</td>
    <td> Docker Swarm agent コンテナ1 号機。このFQDN はDocker Swarm manager の/etc/hosts(--add-host) に登録しておく</td>
  </tr>
  <tr>
    <td> Docker Swarm manager 02 (swagt02)</td>
    <td> 192.168.1.132</td>
    <td> swagt02.example.com</td>
    <td> Debian jessie</td>
    <td> 1.9.1</td>
    <td> Docker Swarm agent コンテナ2 号機。このFQDN はDocker Swarm manager の/etc/hosts(--add-host) に登録しておく</td>
  </tr>
  <tr>
    <td> Docker Swarm manager 03 (swagt03)</td>
    <td> 192.168.1.133</td>
    <td> swagt03.example.com</td>
    <td> Debian jessie</td>
    <td> 1.9.1</td>
    <td> Docker Swarm agent コンテナ3 号機。このFQDN はDocker Swarm manager の/etc/hosts(--add-host) に登録しておく</td>
  </tr>
</tbody></table>

今回はこれらのFQDN を`/etc/hosts` もしくは`--add-host` にて登録しますが、それぞれのホスト及びコンテナが参照するDNS に登録しておくことで、一元管理できるようになります。

## CA の秘密鍵と公開鍵、サーバ証明書を作成する 
Docker Swarm manager ホスト上でopenssl コマンドを実行してCA の秘密鍵と公開鍵を作成します。
ここでは、証明書の作成方法を説明するわけではいので、コマンド内容及び正式な証明書発行手順、ファイルの権限等の詳細な説明は割愛します。


```text:swmgr01
swmgr01~$ sudo mkdir /etc/ssl/docker
swmgr01~$ cd /etc/ssl/docker
swmgr01~$
swmgr01~$ CA_FQDN=ca.docker.example.com
swmgr01~$ CA_CERT=${CA_FQDN}_cert.pem
swmgr01~$ CA_KEY_ENC=${CA_FQDN}_key_enc.pem
swmgr01~$
swmgr01~$ echo "01" | sudo tee ca.srl
swmgr01~$ sudo openssl genrsa -des3 -out $CA_KEY_ENC 2048
swmgr01~$ sudo openssl req -new -x509 -days 365 -key $CA_KEY_ENC -out $CA_CERT \
                  -subj "/C=JP/ST=Tokyo/L=Minatoku/O=Example Company/OU=Development/CN=$CA_FQDN"
```


以上でCA の秘密鍵と証明書の作成は完了です。
次にサーバ証明書を作成していきます。
1 点注意することとして、<codeswmgr01` の証明書は`extendedKeyUsage = clientAuth,serverAuth` を付与して作成する用にしてください。
その他のサーバ`swagt01`,  `swagt02`, `swagt03`については通常のサーバ証明書を作成します。


```text:swmgr01
swmgr01~$ echo "extendedKeyUsage = clientAuth,serverAuth" | sudo tee server_and_client_auth.cnf
swmgr01~$ 
swmgr01~$ SWMGR01_FQDN=swmgr01.example.com
swmgr01~$ SWMGR01_KEY_ENC=${SWMGR01_FQDN}_key_enc.pem
swmgr01~$ SWMGR01_KEY=${SWMGR01_FQDN}_key.pem
swmgr01~$ SWMGR01_CSR=${SWMGR01_FQDN}.csr
swmgr01~$ SWMGR01_CERT=${SWMGR01_FQDN}_cert.pem
swmgr01~$ sudo openssl genrsa -des3 -out $SWMGR01_KEY_ENC 2048
swmgr01~$ sudo openssl rsa -in $SWMGR01_KEY_ENC -out $SWMGR01_KEY
swmgr01~$ sudo openssl req -new -key $SWMGR01_KEY -out $SWMGR01_CSR \
                  -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$SWMGR01_FQDN"
swmgr01~$ sudo openssl x509 -extfile server_and_client_auth.cnf -req -days 365 -in $SWMGR01_CSR -CA $CA_CERT -CAkey $CA_KEY_ENC -out $SWMGR01_CERT
swmgr01~$
swmgr01~$ SWAGT01_FQDN=swagt01.example.com
swmgr01~$ SWAGT01_KEY_ENC=${SWAGT01_FQDN}_key_enc.pem
swmgr01~$ SWAGT01_KEY=${SWAGT01_FQDN}_key.pem
swmgr01~$ SWAGT01_CSR=${SWAGT01_FQDN}.csr
swmgr01~$ SWAGT01_CERT=${SWAGT01_FQDN}_cert.pem
swmgr01~$ sudo openssl genrsa -des3 -out $SWAGT01_KEY_ENC 2048
swmgr01~$ sudo openssl rsa -in $SWAGT01_KEY_ENC -out $SWAGT01_KEY
swmgr01~$ sudo openssl req -new -key $SWAGT01_KEY -out $SWAGT01_CSR \
                  -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$SWAGT01_FQDN"
swmgr01~$ sudo openssl x509 -req -days 365 -in $SWAGT01_CSR -CA $CA_CERT -CAkey $CA_KEY_ENC -out $SWAGT01_CERT
swmgr01~$
swmgr01~$ SWAGT02_FQDN=swagt02.example.com
swmgr01~$ SWAGT02_KEY_ENC=${SWAGT02_FQDN}_key_enc.pem
swmgr01~$ SWAGT02_KEY=${SWAGT02_FQDN}_key.pem
swmgr01~$ SWAGT02_CSR=${SWAGT02_FQDN}.csr
swmgr01~$ SWAGT02_CERT=${SWAGT02_FQDN}_cert.pem
swmgr01~$ sudo openssl genrsa -des3 -out $SWAGT02_KEY_ENC 2048
swmgr01~$ sudo openssl rsa -in $SWAGT02_KEY_ENC -out $SWAGT02_KEY
swmgr01~$ sudo openssl req -new -key $SWAGT02_KEY -out $SWAGT02_CSR \
                  -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$SWAGT02_FQDN"
swmgr01~$ sudo openssl x509 -req -days 365 -in $SWAGT02_CSR -CA $CA_CERT -CAkey $CA_KEY_ENC -out $SWAGT02_CERT
swmgr01~$
swmgr01~$ SWAGT03_FQDN=swagt03.example.com
swmgr01~$ SWAGT03_KEY_ENC=${SWAGT03_FQDN}_key_enc.pem
swmgr01~$ SWAGT03_KEY=${SWAGT03_FQDN}_key.pem
swmgr01~$ SWAGT03_CSR=${SWAGT03_FQDN}.csr
swmgr01~$ SWAGT03_CERT=${SWAGT03_FQDN}_cert.pem
swmgr01~$ sudo openssl genrsa -des3 -out $SWAGT03_KEY_ENC 2048
swmgr01~$ sudo openssl rsa -in $SWAGT03_KEY_ENC -out $SWAGT03_KEY
swmgr01~$ sudo openssl req -new -key $SWAGT03_KEY -out $SWAGT03_CSR \
                  -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$SWAGT03_FQDN"
swmgr01~$ sudo openssl x509 -req -days 365 -in $SWAGT03_CSR -CA $CA_CERT -CAkey $CA_KEY_ENC -out $SWAGT03_CERT
swmgr01~$
swmgr01~$ ls
ca.docker.example.com_cert.pem
ca.docker.example.com_key_enc.pem
ca.srl
swagt01.example.com_cert.pem
swagt01.example.com.csr
swagt01.example.com_key_enc.pem
swagt01.example.com_key.pem
swagt02.example.com_cert.pem
swagt02.example.com.csr
swagt02.example.com_key_enc.pem
swagt02.example.com_key.pem
swagt03.example.com_cert.pem
swagt03.example.com.csr
swagt03.example.com_key_enc.pem
swagt03.example.com_key.pem
swmgr01.example.com_cert.pem
swmgr01.example.com.csr
swmgr01.example.com_key_enc.pem
swmgr01.example.com_key.pem
```


以上でサーバ証明書の作成は完了です。
これらのファイル`*.example.com_cert.pem`、秘密鍵ファイル`*.example.com_key.pem` CA 証明書ファイル`ca.docker.example.com_cert.pem` を各対象サーバの`/etc/ssl/docker` ディレクトリ(Docker コンテナVolume でマウントできるところ)へ転送しておいてください。

続いて、後ほど管理用端末からdocker コマンドでSwarm cluster (Docker Swarm manager)にコマンドを送信するためのclient 証明書を作成します。

```text:client証明書の作成
swmgr01~$ echo "extendedKeyUsage = clientAuth" | sudo tee client_only.cnf
swmgr01~$
swmgr01~$ DOCKER_CLIENT01_FQDN=client01.example.com
swmgr01~$ DOCKER_CLIENT01_KEY_ENC=${DOCKER_CLIENT01_FQDN}_key_enc.pem
swmgr01~$ DOCKER_CLIENT01_KEY=${DOCKER_CLIENT01_FQDN}_key.pem
swmgr01~$ DOCKER_CLIENT01_CSR=${DOCKER_CLIENT01_FQDN}.csr
swmgr01~$ DOCKER_CLIENT01_CERT=${DOCKER_CLIENT01_FQDN}_cert.pem
swmgr01~$ sudo openssl genrsa -des3 -out $DOCKER_CLIENT01_KEY_ENC 2048
swmgr01~$ sudo openssl rsa -in $DOCKER_CLIENT01_KEY_ENC -out $DOCKER_CLIENT01_KEY
swmgr01~$ sudo openssl req -config /etc/ssl/openssl.cnf -new -key $DOCKER_CLIENT01_KEY -out $DOCKER_CLIENT01_CSR \
                  -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$DOCKER_CLIENT01_FQDN"
swmgr01~$ sudo openssl x509 -extfile client_only.cnf -req -days 365 -in $DOCKER_CLIENT01_CSR -CA $CA_CERT -CAkey $CA_KEY_ENC -out $DOCKER_CLIENT01_CERT
```


各証明書ファイルを作成したら、以下の通り証明書ファイル及び秘密鍵ファイルを各Docker Swarm agent `swagt01-03` の`/etc/ssl/docker` ディレクトリに転送しておいてください。
転送が完了したら、各ファイルがDocker daemon から読み取りできる権限に設定をしておいてください。

転送しておくファイルについてはそれぞれ以下のとおりです。

```text:swagt01
swagt01~# ls -1 /etc/ssl/docker/
ca.docker.example.com_cert.pem      # CA の証明書
swagt01.example.com_cert.pem        # swagt01 用サーバ証明書
swagt01.example.com_key.pem         # swagt01 用サーバ証明書の秘密鍵
```



```text:swagt02
swagt02~# ls -1 /etc/ssl/docker/
ca.docker.example.com_cert.pem
swagt02.example.com_cert.pem
swagt02.example.com_key.pem
```



```text:swagt03
swagt03~# ls -1 /etc/ssl/docker/
ca.docker.example.com_cert.pem
swagt03.example.com_cert.pem
swagt03.example.com_key.pem
```



## TLS 認証を行うにあたり事前準備 
証明書認証ON でDocker Swarm agent を起動するにあたり、前回記事でDocker Swarm manager 01, Docker Swarm agent 01-03 コンテナが作成され起動している場合、事前にコンテナを停止して削除しておくようにしてください(理屈的にはswagt01-03 のコンテナは同じものを使いまわせるのですが、念の為…)。


```text:swmgr01
$ docker stop swmgr01
$ docker rm swmgr01
```



```text:swagt01
$ docker stop swagt01
$ docker rm swagt01
```



```text:swagt02
$ docker stop swagt02
$ docker rm swagt02
```



```text:swagt03
$ docker stop swagt03
$ docker rm swagt03
```



## TLS による認証機能をON にしてDocker Swarm agent 01-03 のDocker ホストのDocker daemon を起動する 
Docker Swarm agent 01-03 のTLS 認証機能を使うには、Docker Swarm agent のDocker ホストのDocker daemon のTLS 機能を有効にします。
`/lib/systemd/system/docker.service` ファイルを開き`ExecStart` の値を次のように設定します。


```text:/lib/systemd/system/docker.serviceatswagt01
ExecStart=/usr/bin/docker daemon --tlsverify --tlscacert=/etc/ssl/docker/ca.docker.example.com_cert.pem --tlscert=/etc/ssl/docker/swagt01.example.com_cert.pem --tlskey=/etc/ssl/docker/swagt01.example.com_key.pem -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock
```



```text:/lib/systemd/system/docker.serviceatswagt02
ExecStart=/usr/bin/docker daemon --tlsverify --tlscacert=/etc/ssl/docker/ca.docker.example.com_cert.pem --tlscert=/etc/ssl/docker/swagt02.example.com_cert.pem --tlskey=/etc/ssl/docker/swagt02.example.com_key.pem -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock
```



```text:/lib/systemd/system/docker.serviceatswagt03
ExecStart=/usr/bin/docker daemon --tlsverify --tlscacert=/etc/ssl/docker/ca.docker.example.com_cert.pem --tlscert=/etc/ssl/docker/swagt03.example.com_cert.pem --tlskey=/etc/ssl/docker/swagt03.example.com_key.pem -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock
```


各サーバの`/lib/systemd/system/docker.service` ファイルを書き換えたら各サーバ上で`systemctl daemon-reload` を実行してdocker を再起動します。


```text:swagt01-03
# systemctl daemon-reload
# systemctl restart docker
```


## Docker agent をcluster に参加させる 
各Docker Swarm agent で`swarm join` コマンドを実行してcluster に参加させます。


```text:swagt01
$ docker run --name swagt02 -d swarm join --addr=swagt02.example.com:2376 token://8f620653b5157592418a2da287dc722d
```



```text:swagt02
$ docker run --name swagt02 -d swarm join --addr=swagt02.example.com:2376 token://8f620653b5157592418a2da287dc722d
```



```text:swagt03
$ docker run --name swagt03 -d swarm join --addr=swagt03.example.com:2376 token://8f620653b5157592418a2da287dc722d
```




```text:swmgr01
$ docker run --rm swarm list token://8f620653b5157592418a2da287dc722d
swagt03.example.com:2376
swagt02.example.com:2376
swagt01.example.com:2376
```



## TLS による認証機能をON にしてDocker Swarm manager 01 を起動する 
`swmgr01` ノードで次のコマンドを実行してDocker Swarm manager 01 を起動します。
起動するときに`--tlsverify`, `--tlscacert`, `--tlscert`, `--tlskey` オプションを加えてTLS 通信に使用する証明書ファイル及び秘密鍵を指定するようにしてください。
また、他のノードの名前解決ができるように`--add-host` オプションで名前解決の定義を追加し、Docker ホストの2376 port にバインドするように指定します。


```text:swmgr01
swmgr01~$ docker run --name swmgr01 -d -v /etc/ssl/docker:/etc/ssl/docker -p 2376:2375 \
              --add-host swagt01.example.com:192.168.1.131 --add-host swagt02.example.com:192.168.1.132 --add-host swagt03.example.com:192.168.1.133 \
              swarm manage --tlsverify \
              --tlscacert=/etc/ssl/docker/ca.docker.example.com_cert.pem \
              --tlscert=/etc/ssl/docker/swmgr01.example.com_cert.pem \
              --tlskey=/etc/ssl/docker/swmgr01.example.com_key.pem \
              token://8f620653b5157592418a2da287dc722d
```


## Docker Swarm manager 01 の起動状態を確認する 
`docker info` コマンドを使ってDocker Swarm manager 01 が起動していることを確認します。
TLS 認証を使用して実行することになるので、コマンドは以下のようになります。


```text:swmgr01
$ docker --tlsverify --tlscacert=/etc/ssl/docker/ca.docker.example.com_cert.pem --tlscert=/etc/ssl/docker/client01.example.com_cert.pem --tlskey=/etc/ssl/docker/client01.example.com_key.pem -H tcp://swmgr01.example.com:2376 info
Containers: 0
Images: 0
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 0
CPUs: 0
Total Memory: 0 B
Name: 5e38ce882c24
```


また、`ps -a` コマンドを実行して、各Docker Swarm agent 上で起動しているコンテナを確認してみましょう。

```text
$ docker --tlsverify -H tcp://swmgr01.example.com:2376 ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
da4ed91cc851        swarm               "/swarm join --addr=s"   About a minute ago   Up About a minute   2375/tcp            swagt03/swagt03
c55b9bb6f605        swarm               "/swarm join --addr=s"   2 minutes ago        Up 2 minutes        2375/tcp            swagt02/swagt02
b5ebf34afd62        swarm               "/swarm join --addr=s"   2 minutes ago        Up 2 minutes        2375/tcp            swagt01/swagt01
```


上記のように結果が出力されれば成功です。
以上でDocker Swarm cluster をTLS 化する手順は完了です。

### 補足: ps -a コマンドで全てのDocker Swarm agent が表示されない場合 
詳しい原因はわかっていませんが、`docker --tlsverify -H tcp://swmgr01.example.com:2376 ps -a` コマンドを実行した時に全てのDocker Swarm agent ノード上のコンテナが表示されないことがあります。
その場合は、Docker Swarm manager 01 のDocker Swarm manager コンテナを一旦削除してから、再度Docker Swarm manager コンテナを起動してみてください。

### 補足: TLS 関連のオプションを省略する 
TLS を使ったコマンドの発行ができることは確認できましたが、これではオプションが冗長で毎回指定していられないので、証明書及び鍵を明示的に指定しないで実行できるようにします。
`~/.docker` ディレクトリを新規に作成し、そこに`ca.pem`, `cert.pem`, `key.pem` というファイル名でそれぞれclient 証明書とCA の証明書ファイルを設置しておきます。
今回は既に`/etc/ssl/docker` ディレクトリにclient 用の証明書及び秘密鍵が用意されているのでそれに対してシンボリックリンクを作成して対応します。


```text:~/.docker
$ cd ~
$ mkdir ~/.docker
$ cd .docker
$ ln -s /etc/ssl/docker/ca.docker.example.com_cert.pem ca.pem
$ ln -s /etc/ssl/docker/client01.example.com_cert.pem cert.pem
$ ln -s /etc/ssl/docker/client01.example.com_key.pem key.pem
```


ファイルの準備ができたらもう一度次のように`docker info` コマンドを実行してみましょう。


```text:dockerinfo
$ docker --tlsverify -H tcp://swmgr01.example.com:2376 info
Containers: 0
Images: 0
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 0
CPUs: 0
Total Memory: 0 B
Name: 5e38ce882c24
```


先ほどと同様な内容が出力されれば成功です。

### 補足: 更にオプションを省略したい 
更に`docker` コマンドの`-H` 及び`--tlsverify` オプションを省略したい場合、`DOCKER_HOST`, `DOCKER_TLS_VERIFY` 環境変数を以下のように設定します。


```text:swmgr01
export DOCKER_HOST=tcp://swmgr01.example.com:2376
export DOCKER_TLS_VERIFY=1
```


なお、本説明ではこの環境変数は設定せずに続けていきます。

### 補足: Docker client の証明書ファイルを保管する場所について 
Docker コマンド実行時に使用する証明書ファイル、秘密鍵ファイルの保管場所を別の場所にしたい場合、`DOCKER_CERT_PATH` 環境変数を設定してディレクトリを指定するようにします。
例えば`~/.docker/swmgr01.example.com` ディレクトリに変更したい場合は次のようにします。


```text:DOCKER_CERT_PATH
$ export DOCKER_CERT_PATH=~/.docker/swmgr01.example.com
```


なお、本説明ではこの環境変数は設定せずに続けていきます。

## Docker swarm cluster 上にコンテナを作成してみる 
試しにDocker Swarm cluster 上にbusybox コンテナを作成してみましょう。
コマンドは次のようになります。


```text:busyboxコンテナを作成してみる
# docker -H tcp://swmgr01.example.com:2376 --tlsverify run --name test_busybox -ti busybox /bin/sh
/ # id 
uid#0(root) gid=0(root) groups10(wheel)
/ # hostname
7da820ef32bf
/ # exit
```


上記のようにbusybox のプロンプトが表示されればコンテナの起動は成功です。
次に、このコンテナがどのDocker Swarm agent 上に作成されているかを、`docker ps -a` コマンドを使って確認してみましょう。


```text:dockerps-a
$ docker -H tcp://swmgr01.example.com:2376 --tlsverify ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
7da820ef32bf        busybox             "/bin/sh"                3 minutes ago       Exited (0) 2 minutes ago                       swagt03/test_busybox
a09b115c23ac        swarm               "/swarm join --addr=s"   13 minutes ago      Up 13 minutes              2376/tcp            swagt03/swagt03
e7c6ad6c04e0        swarm               "/swarm join --addr=s"   13 minutes ago      Up 13 minutes              2376/tcp            swagt02/swagt02
7656721e2cb8        swarm               "/swarm join --addr=s"   46 hours ago        Up 23 minutes              2376/tcp            swagt01/swagt01
```


コマンドの出力結果を見てみると、busybox コンテナがswagt03 に作成されていることがわかります。
実際、どのDocker Swarm agent ノードにコンテナが作成されるかは、環境によって異なる可能性が有ります。

続けて幾つかのコンテナを作成し、もう一度`docker ps -a` コマンドでコンテナがどこに作成されるかを確認してみましょう。


```text:dockerps-a
$ docker -H tcp://swmgr01.example.com:2376 --tlsverify ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                        PORTS               NAMES
e5b10b3b5443        redis               "/entrypoint.sh redis"   42 seconds ago      Exited (127) 40 seconds ago                       swagt03/test_hello_redis
a640ba5f165a        mysql               "/entrypoint.sh mysql"   5 minutes ago       Exited (1) 5 minutes ago                          swagt01/test_mysql
85b1655aa3f9        node                "node"                   10 minutes ago      Exited (0) 9 minutes ago                          swagt02/test_nodejs
2af70f9ebbbd        debian              "/bin/bash"              18 minutes ago      Exited (130) 14 minutes ago                       swagt01/test_debian
7da820ef32bf        busybox             "/bin/sh"                28 minutes ago      Exited (0) 27 minutes ago                         swagt03/test_busybox
a09b115c23ac        swarm               "/swarm join --addr=s"   38 minutes ago      Up 38 minutes                 2376/tcp            swagt03/swagt03
e7c6ad6c04e0        swarm               "/swarm join --addr=s"   38 minutes ago      Up 38 minutes                 2376/tcp            swagt02/swagt02
7656721e2cb8        swarm               "/swarm join --addr=s"   47 hours ago        Up 48 minutes                 2376/tcp            swagt01/swagt01
```


上記の用にDocker Swarm cluster 上のノードに分散して作成されていることがわかります。
以上でDocker Swarm cluster をTLS 化して動作を確認するまでの手順は完了です。


## おまけ: 各証明書(public key, private key pair)をECC(楕円曲線暗号)で作成する 
2016/01 現在、証明書の作成手順は多くのWeb に転がっている資料によるとRSA 方式で作成されていますが、ここで次世代の暗号方式として注目されているECC で各証明書を作成してDocker Swarm cluster 内で利用してみましょう。
ECC 形式にすることで、RSA よりも少ない鍵長でより高い暗号強度を得ることができるようになるといわれています。

ここではswmgr01 のDocker ホスト上でECC で証明書を作成した時の手順だけを残しておきます。
その他、証明書の設置手順についてはこれまでで説明した手順と変わりありません。


```text:CreateCACertificatewithECC
sudo mkdir /etc/ssl/docker
cd /etc/ssl/docker
echo "01" | sudo tee ca.srl

CA_FQDN=ca.docker.example.com
CA_CERT=${CA_FQDN}_cert.pem
CA_KEY=${CA_FQDN}_key.pem

sudo openssl ecparam -out $CA_KEY -name prime256v1 -genkey
sudo openssl req -new -x509 -days 365 -key $CA_KEY -out $CA_CERT \
        -subj "/C=JP/ST=Tokyo/L=Minatoku/O=Example Company/OU=Development/CN=$CA_FQDN"
```



```text:Createswmgr01'sCertificatewithECC
echo "extendedKeyUsage = clientAuth,serverAuth" | sudo tee server_and_client_auth.cnf

SWMGR01_FQDN=swmgr01.example.com
SWMGR01_KEY=${SWMGR01_FQDN}_key.pem
SWMGR01_CSR=${SWMGR01_FQDN}.csr
SWMGR01_CERT=${SWMGR01_FQDN}_cert.pem
sudo openssl ecparam -out $SWMGR01_KEY -name prime256v1 -genkey
sudo openssl req -new -key $SWMGR01_KEY -sha256 -out $SWMGR01_CSR \
        -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$SWMGR01_FQDN"
sudo openssl x509 -extfile server_and_client_auth.cnf -req -days 365 -in $SWMGR01_CSR -CA $CA_CERT -CAkey $CA_KEY -out $SWMGR01_CERT
```



```text:Createswagt01'sCertificatewithECC
SWAGT01_FQDN=swagt01.example.com
SWAGT01_KEY=${SWAGT01_FQDN}_key.pem
SWAGT01_CSR=${SWAGT01_FQDN}.csr
SWAGT01_CERT=${SWAGT01_FQDN}_cert.pem
sudo openssl ecparam -out $SWAGT01_KEY -name prime256v1 -genkey
sudo openssl req -new -key $SWAGT01_KEY -sha256 -out $SWAGT01_CSR \
        -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$SWAGT01_FQDN"
sudo openssl x509 -req -days 365 -in $SWAGT01_CSR -CA $CA_CERT -CAkey $CA_KEY -out $SWAGT01_CERT
```



```text:Createswagt02'sCertificatewithECC
SWAGT02_FQDN=swagt02.example.com
SWAGT02_KEY=${SWAGT02_FQDN}_key.pem
SWAGT02_CSR=${SWAGT02_FQDN}.csr
SWAGT02_CERT=${SWAGT02_FQDN}_cert.pem
sudo openssl ecparam -out $SWAGT02_KEY -name prime256v1 -genkey
sudo openssl req -new -key $SWAGT02_KEY -sha256 -out $SWAGT02_CSR \
        -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$SWAGT02_FQDN"
sudo openssl x509 -req -days 365 -in $SWAGT02_CSR -CA $CA_CERT -CAkey $CA_KEY -out $SWAGT02_CERT
```



```text:Createswagt03'sCertificatewithECC
SWAGT03_FQDN=swagt03.example.com
SWAGT03_KEY=${SWAGT03_FQDN}_key.pem
SWAGT03_CSR=${SWAGT03_FQDN}.csr
SWAGT03_CERT=${SWAGT03_FQDN}_cert.pem
sudo openssl ecparam -out $SWAGT03_KEY -name prime256v1 -genkey
sudo openssl req -new -key $SWAGT03_KEY -sha256 -out $SWAGT03_CSR \
        -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$SWAGT03_FQDN"
sudo openssl x509 -req -days 365 -in $SWAGT03_CSR -CA $CA_CERT -CAkey $CA_KEY -out $SWAGT03_CERT
```



```text:Createswagt03'sCertificatewithECC
DOCKER_CLIENT01_FQDN=client01.example.com
DOCKER_CLIENT01_KEY=${DOCKER_CLIENT01_FQDN}_key.pem
DOCKER_CLIENT01_CSR=${DOCKER_CLIENT01_FQDN}.csr
DOCKER_CLIENT01_CERT=${DOCKER_CLIENT01_FQDN}_cert.pem
sudo openssl ecparam -out $DOCKER_CLIENT01_KEY -name prime256v1 -genkey
sudo openssl req -config /etc/ssl/openssl.cnf -new -key $DOCKER_CLIENT01_KEY -sha256 -out $DOCKER_CLIENT01_CSR \
        -subj "/C=JP/ST=Tokyo/L=Hoge/O=Example Company/OU=Development/CN=$DOCKER_CLIENT01_FQDN"
sudo openssl x509 -extfile client_only.cnf -req -days 365 -in $DOCKER_CLIENT01_CSR -CA $CA_CERT -CAkey $CA_KEY -out $DOCKER_CLIENT01_CERT
```


# 参考 
<dl>
  <dt> Docker Swarm overview</dt>
  <dd> https://docs.docker.com/swarm/</dd>
</dl>

<dl>
  <dt> Install and Create a Docker Swarm</dt>
  <dd> https://docs.docker.com/swarm/install-w-machine/</dd>
</dl>

<dl>
  <dt> Docker Tutorial : Getting Started With Docker Swarm</dt>
  <dd> http://devopscube.com/docker-tutorial-getting-started-with-docker-swarm/</dd>
</dl>

<dl>
  <dt> Create a swarm for development</dt>
  <dd> https://docs.docker.com/swarm/install-manual/</dd>
</dl>

<dl>
  <dt> DOCKER SWARM WITH TLS AUTHENTICATION</dt>
  <dd> http://www.blackfinsecurity.com/docker-swarm-with-tls-authentication/</dd>
</dl>

<dl>
  <dt> Protect the Docker daemon socket</dt>
  <dd> https://docs.docker.com/engine/articles/https/</dd>
</dl>

<dl>
  <dt> Docker Swarmで複数Dockerホストからクラスタを作る</dt>
  <dd> http://blog.takanabe.tokyo/2015/11/23/1565/</dd>
</dl>

<dl>
  <dt> etcd security model</dt>
  <dd> https://coreos.com/etcd/docs/0.4.7/etcd-security/</dd>
</dl>

<dl>
  <dt> Intro to Docker Swarm: Part 2 - Configuration Options and Requirements</dt>
  <dd> http://www.hnwatcher.com/r/1644394/Intro-to-Docker-Swarm-Part-2-Comfiguration-Modes-and-Requirements</dd>
</dl>