Docker 1.13の気になる変更点と新機能

# はじめに
この記事は[CrowdWorks Advent Calendar 2016](http://qiita.com/advent-calendar/2016/crowdworks) の1日目の記事です。[CrowdWorks](https://crowdworks.jp)のエンジニアが毎日なにかを書きます。

Docker 1.13がそろそろ出そうです。この記事を書いてる時点ではまだRC版ですが、正式版のリリースは[2016/12/8頃の予定](https://github.com/docker/docker/blob/master/CHANGELOG.md#1130-2016-12-08)となっているようです。(※2017/01/20追記：当初予定より１ヶ月ちょっと遅延して最終的に2017/01/18に正式版がリリースされました。)

Docker 1.12ではDockerクラスタを管理するswarmがDocker Engine本体に統合されましたが、Docker 1.13ではそのswarm関連の多くの改善が含まれています。
特に注目すべきはswarmクラスタに複数のサービスをまとめてデプロイする `docker stack` コマンド群のExperimental指定が外れたことと、`docker stack deploy --compose-file` で `docker-compose.yml` を直接デプロイできるようになったことじゃないかなー。

というわけで、気になる変更点と新機能を眺めつつ、そのうちの一部、主にswarm関連を実際に試してみた。

# 気になる変更点と新機能
Docker1.13には多くの変更点が含まれます。すべての変更点は [CHANGELOG](https://github.com/docker/docker/blob/master/CHANGELOG.md#1130-2016-12-08) を参照して下さい。

以下では個人的に気になるものを抜粋します。
分類はCHANGELOGに合わせていますが、並び順は若干異なります。
また1.13.0-rc2版時点の情報であるため、正式リリース時点では異なる可能性があることを予めご承知おきください。

## Remote API(v1.25)&Client
* Support `docker stack deploy` from a Compose file [#27998](https://github.com/docker/docker/pull/27998)
    * swarmクラスタに `docker-compose.yml` を直接デプロイできるようになりました。
    * Docker 1.12でdocker-compose.ymlをswarmクラスタにデプロイするには、 [DAB (Distributed Application Bundle)](https://blog.docker.com/2016/06/docker-app-bundle/) という仕組みで、 `docker-compose.yml` を一旦 `docker-compose bundle` で `.dab` ファイルを生成してから `docker stack deploy` する必要があったんだけど、Docker 1.13から `docker-compose` コマンドへの依存がなくなり、中間ファイルを生成することなく `docker-compose.yml` を直接読み込んでswarmにデプロイできるようになった。
    * ただbuildは使えなかったりとか現状サポートされている命令は一部で限定的なので、既存のローカルで使ってたdocker-compose.ymlがなんでもデプロイできるわけではないことに注意。buildはservice createする前にどこかにpushしないといけないし、まぁ構造上どう考えても難しいよね。
* Add --env-file flag to docker create service [#24844](https://github.com/docker/docker/pull/24844)
    * `docker service create` で `--env-file` が渡せるようになった。頑張ってbashでループして `-e` しなくて済む。
* Add --no-trunc to service/node/stack ps output [#25337](https://github.com/docker/docker/pull/25337)
    * `docker service ps` とかで見たときにエラーメッセージが途中で切れててinspectしないと全文見えなかったのが、`--no-trunc` 指定すると省略せずに出せるようになった。デバッグ捗る。
* Allow client to talk to an older server [#27745](https://github.com/docker/docker/pull/27745)
    * クライアントの方がサーバよりもAPIバージョンが新しい場合でも、互換性のあるバージョンにダウングレードさせて通信できるようにする仕組みの導入。この機能自体がサーバ側にないといけないので、すぐには恩恵は受けられないけど今後の布石。
* (experimental) Implement checkpoint and restore [#22049](https://github.com/docker/docker/pull/22049)
    * 稼働中のコンテナのスナップショットとリストアできるようにする実験。同一ホスト内のみで、いわゆるlive migration的なことはできないみたい。

## Swarm Mode
* (experimental) Add docker service logs command to view logs for a service [#28089](https://github.com/docker/docker/pull/28089)
    * サービス単位でdocker logsを見れるようになった。fluentなどでログ集約してない素の状態だとコンテナ単位でdocker logsしないといけなくてめんどくさかったのだけど、サービス単位で見れると地味に便利。
* Add --force to docker service update [#27596](https://github.com/docker/docker/pull/27596)
    * `docker service update` で設定に何も変更がなくても `--force` で読み込み直してコンテナをリバランスさせたりできるようになる。
* Pin images by digest for docker service create and update [#28173](https://github.com/docker/docker/pull/28173)
    * latestタグなどの動的に変わる可能性のあるイメージが、サービス内のコンテナ間で同一のものを参照するように、service create/update時のイメージのダイジェストで固定する。最新をpullしなおして更新したい場合は `docker service update --image` すればよいみたい。
* Add secret management [#27794](https://github.com/docker/docker/pull/27794)
    * コンテナ内に秘匿情報を渡すのに `docker secret` という仕組みができた。内部的にswarmkitのsecret APIを使ってるので、swarm modeでしか使えないよう。

## Networking
* Add --attachable network support to enable docker run to work in swarm-mode overlay network [#25962](https://github.com/docker/docker/pull/25962)
    * `docker run` でもswarmのoverlay networkに接続できるようになった。何がうれしいかというとswarmのserviceは常駐を前提にしてるので、単発タスクと組み合わせできなくて不便だったのが、これによりoverlay network内で常駐しない単発タスクは `docker run` で混ぜて使えるようになった。

## Runtime
* Add --experimental daemon flag to enable experimental features, instead of shipping them in a separate build [#27223](https://github.com/docker/docker/pull/27223)
    * 以前はExperimental版は別のバイナリとして配布されていたが、同一バイナリとなりdockerd起動時のオプションで切り替えできるようになった。Experimentalな新機能が試しやすくなる。
* Add new docker system command with df and prune subcommands for system resource management, as well as docker {container,image,volume,network} prune subcommands [#26108](https://github.com/docker/docker/pull/26108) [#27525](https://github.com/docker/docker/pull/27525)
    * `docker system df` というディスク使用量などを簡単にチェックできるコマンドができた。
    * `docker system prune` というゴミ消しコマンドができた。docker runで　`--rm` 付け忘れて残っちゃったコンテナとか、参照されていないImageやVolume、使われていないNetworkなどを一括でお掃除してくれる。いいかんじのワンライナー書かなくてよくなった。

## Builder
* Add capability to specify images used as a cache source on build. These images do not need to have local parent chain and can be pulled from other registries [#26839](https://github.com/docker/docker/pull/26839)
    * `docker build --cache-from` でローカルにないビルドキャッシュをリモートから取得できるようになった。
* (experimental) Add option to squash image layers to the FROM image after successful builds [#22641](https://github.com/docker/docker/pull/22641)
    * `docker build --squash` でビルド時のイメージレイヤをまとめることができるようにする。

## DEPRECATION
* Deprecate MAINTAINER in Dockerfile [#25466](https://github.com/docker/docker/pull/25466)
    * Dockerfileの `MAINTAINER` 命令が非推奨になります。より汎用的な `LABEL` を使えということらしい。特に警告が出たりはしないようなので、既存のDockerfileにすぐに影響はなさそうだけど、少なくとも新規にDockerfileを書く場合は `MAINTAINER` を使うのはやめよう。

## CHAGELOGに書いてないけど
* Move `docker stack` out of experimental [#28677](https://github.com/docker/docker/pull/28677)
    * `docker stack` コマンド群がExperimentalではなくなった
    * rc1からrc2の間にマージされたからか(?)現時点まだCHANGELOGに書いてないけど、一応ここに載せておく。

# 検証
というわけでさっそく一部の機能を試してみた。主にswarm関連のものを中心に。

## 検証環境
検証用にAWS EC2上に Ubuntu 16.04 を2台立て、node1をswarmのmanager、node2をworkerとして使いました。
補足としてswarmノード間で以下の通信許可が必要です。

* TCP(2377): cluster management communications
* TCP/UDP(7946): communication among nodes
* TCP/UDP(4789): overlay network traffic
 
検証時点のDockerのバージョンは1.13.0-rc2です。
正式リリース版では動作が異なる可能性があることを予めご承知おきください。

```
root@node1:~# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

root@node1:~# uname -a
Linux node1 4.4.0-45-generic #66-Ubuntu SMP Wed Oct 19 14:12:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
```

## RC版のインストール
正式リリース前のRC版は `test.docker.com` で配布されています。 
正式リリースされれば`get.docker.com` から配布されます。

```
root@node1:~# curl -fsSL https://test.docker.com/ | sh
```

```
root@node1:~# docker version
Client:
 Version:      1.13.0-rc2
 API version:  1.25
 Go version:   go1.7.3
 Git commit:   1f9b3ef
 Built:        Wed Nov 23 06:32:39 2016
 OS/Arch:      linux/amd64

Server:
 Version:             1.13.0-rc2
 API version:         1.25
 Minimum API version: 1.12
 Go version:          go1.7.3
 Git commit:          1f9b3ef
 Built:               Wed Nov 23 06:32:39 2016
 OS/Arch:             linux/amd64
 Experimental:        false
```

node2も同様にインストールしました。

## Experimentalモードの有効化

一部の機能はまだExperimental扱いで通常モードでは使えないので、全機能を使うにはExperimentalフラグを有効化します。
Docker 1.12まではExperimental版は別のバイナリとして配布されていましたが、
Docker 1.13から同一バイナリとなりdockerd起動時のオプションで切り替えできるようになりました。

```
root@node1:~# vi /etc/docker/daemon.json
root@node1:~# cat /etc/docker/daemon.json
{
  "experimental": true
}
root@node1:~# systemctl restart docker.service
root@node1:~# docker version
Client:
 Version:      1.13.0-rc2
 API version:  1.25
 Go version:   go1.7.3
 Git commit:   1f9b3ef
 Built:        Wed Nov 23 06:32:39 2016
 OS/Arch:      linux/amd64

Server:
 Version:             1.13.0-rc2
 API version:         1.25
 Minimum API version: 1.12
 Go version:          go1.7.3
 Git commit:          1f9b3ef
 Built:               Wed Nov 23 06:32:39 2016
 OS/Arch:             linux/amd64
 Experimental:        true
```

node2も同様に設定しました。

## swarmクラスタの初期化

node1をmanagerとしてswarmクラスタを初期化します。

```
root@node1:~# docker swarm init
Swarm initialized: current node (emit8i9n4tplyd29ewvta2usy) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-3u4ig055yrxmyy1apjl1860gstbbaxng6xjiwpjnet6bv0ur2t-56l28ag60taqjsimnybyd0stx \
    172.31.9.117:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
```

node2でworkerとしてswarmクラスタに参加します。

```
root@node2:~# docker swarm join \
>     --token SWMTKN-1-3u4ig055yrxmyy1apjl1860gstbbaxng6xjiwpjnet6bv0ur2t-56l28ag60taqjsimnybyd0stx \
>     172.31.9.117:2377
This node joined a swarm as a worker.
```

クラスタの初期化され、node1がmanager、node2がworkerになってます。

```
root@node1:~# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
b57tzjj8jytnhmw32sy277i70    node2     Ready   Active
emit8i9n4tplyd29ewvta2usy *  node1     Ready   Active        Leader
```

## docker stack deploy --compose-file
適当なdocker-compose.ymlを用意して `version: "3"` を指定します。

```
root@node1:~# vi docker-compose.yml
root@node1:~# cat docker-compose.yml
version: '3'

services:
  client:
    image: tutum/curl
    command: "tail -f /dev/null"

  web:
    image: nginx
    ports:
      - 80
```

デプロイしてみます。

```
root@node1:~# docker stack deploy --compose-file ./docker-compose.yml hoge
Creating network hoge_default
Creating service hoge_web
Creating service hoge_client
```

overlay networkが作成され、serviceがデプロイされていることが分かります。

```
root@node1:~# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
fcbbde5d9b68        bridge              bridge              local
3c7c466d2a90        docker_gwbridge     bridge              local
165zncwuahxl        hoge_default        overlay             swarm
3cfe33f4ace7        host                host                local
n400ahliwjq2        ingress             overlay             swarm
ee7989b6aa25        none                null                local

root@node1:~# docker service ls
ID            NAME         MODE        REPLICAS  IMAGE
il98obja9tu9  hoge_client  replicated  1/1       tutum/curl:latest
v8ra4btbvlxd  hoge_web     replicated  1/1       nginx:latest
```

swarmクラスタ内のmanagerとworkerに分散配置されていることも確認できます。

```
root@node1:~# docker service ps hoge_client
NAME                        IMAGE              NODE   DESIRED STATE  CURRENT STATE               ERROR  PORTS
hoge_client.1.16kh4m2yq51s  tutum/curl:latest  node2  Running        Running about a minute ago
root@node1:~# docker service ps hoge_web
NAME                     IMAGE         NODE   DESIRED STATE  CURRENT STATE               ERROR  PORTS
hoge_web.1.ns6p315r7w86  nginx:latest  node1  Running        Running about a minute ago
```

ちょっとコンテナ内からcurlを打ってみましょう。

```
root@node2:~# docker ps
CONTAINER ID        IMAGE                                                                                COMMAND               CREATED             STATUS              PORTS               NAMES
5c318bb7d464        tutum/curl@sha256:b6f16e88387acd4e6326176b212b3dae63f5b2134e69560d0b0673cfb0fb976f   "tail -f /dev/null"   3 minutes ago       Up 3 minutes                            hoge_client.1.16kh4m2yq51styx54ol4efm7a
root@node2:~# docker exec -it 5c318bb7d464 /bin/bash
root@5c318bb7d464:/# curl http://web/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```

ちゃんとノードをまたいでクラスタ内で通信できてますね。

この `version: "3"` フォーマットはドキュメントが見つけられなかったのだけど、 試しに `build` とか指定するとこんな警告メッセージが出て、

```
Ignoring unsupported options: build
```

サポートされてないものを指定すると怒られるよう。

このメッセージを吐いてるのはコードを眺めてみるとこの辺で、
https://github.com/docker/docker/blob/1f9b3ef9e9c74c2905780ac5347d018646a20022/cli/command/stack/deploy.go#L92

コードを辿っていくとこの辺がブラックリストのように見えるんだけど、
https://github.com/docker/docker/blob/1f9b3ef9e9c74c2905780ac5347d018646a20022/vendor/github.com/aanand/compose-file/types/types.go#L7-L44

現状何が使えて何が使えないのかは、そのうちドキュメントがちゃんと整備されるんじゃなかろうか。
まだ出来たてホヤホヤ感がありますね。

(※2017/01/20追記：composeのv3フォーマットも[公式ドキュメント](https://docs.docker.com/compose/compose-file/)に記載されました)

## docker service logs

Docker1.12まではコンテナ単位docker logsするしかなかったんですが、サービス単位でログが見れるようになった。地味にうれしい。

```
root@node1:~# docker service logs -f hoge_web
hoge_web.1.ns6p315r7w86@node1    | 10.0.0.5 - - [26/Nov/2016:04:14:28 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.35.0" "-"
```

## docker network create --attachable
docker runで先程のoverlay networkに接続しようと、とりあえず試してみたところ、デフォルトでは有効ではなかった。

```
root@node1:~# docker run -it --rm --net hoge_default tutum/curl curl http://web/
docker: Error response from daemon: Could not attach to network hoge_default: rpc error: code = 7 desc = network hoge_default not manually attachable.
```

どうやら `docker network create` するとき `--attachable` を指定していると、通常のdocker runでも接続できるようになるようですが、さっき作ったnetworkを見てみると、デフォルトでは `Attachable: false` になっていて有効になっていないようです。 

```
root@node1:~# docker network inspect --format="{{ .Attachable }}" hoge_default
false
```

`docker network update` というコマンドは現状なさそうなので、検証用に別のnetworkを作って試してみます。

```
root@node1:~# docker network create --driver overlay fuga --attachable
4gu9jty5f5mib3m8zeab7bel2
root@node1:~# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
fcbbde5d9b68        bridge              bridge              local
3c7c466d2a90        docker_gwbridge     bridge              local
4gu9jty5f5mi        fuga                overlay             swarm
165zncwuahxl        hoge_default        overlay             swarm
3cfe33f4ace7        host                host                local
n400ahliwjq2        ingress             overlay             swarm
ee7989b6aa25        none                null                local
root@node1:~# docker service create --network fuga -p 80 --name fuga_nginx nginx
vg7dmcl1a3ty633lhatyakypp
root@node1:~# docker service ps fuga_nginx
NAME                       IMAGE         NODE   DESIRED STATE  CURRENT STATE           ERROR  PORTS
fuga_nginx.1.itkn421x5dt0  nginx:latest  node1  Running        Running 15 seconds ago
```

作ったoverlay network上でdocker runしてみます。

```
root@node1:~# docker run -it --rm --net fuga tutum/curl curl http://fuga_nginx/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```

docker runでもoverlay networkに接続できてますね。

## docker service update --force

適当なサービスを作って、コンテナ数を2個にします。

```
root@node1:~# docker service create --replicas 2 --name test nginx
b9pfgwe8o0o0jav7acqywj78q
root@node1:~# docker service ls
ID            NAME  MODE        REPLICAS  IMAGE
b9pfgwe8o0o0  test  replicated  2/2       nginx:latest
```

node1/node2にそれぞれ分散されています。

```
root@node1:~# docker service ps test
NAME                 IMAGE         NODE   DESIRED STATE  CURRENT STATE          ERROR  PORTS
test.1.gqik60uihoh2  nginx:latest  node1  Running        Running 9 seconds ago
test.2.ttfi9a0bsh9n  nginx:latest  node2  Running        Running 9 seconds ago
```

わざとバランスを崩すために一時的にnode2をdrainしてactiveに戻します。

```
root@node1:~# docker node update --availability drain node2
node2
root@node1:~# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
b57tzjj8jytnhmw32sy277i70    node2     Ready   Drain
emit8i9n4tplyd29ewvta2usy *  node1     Ready   Active        Leader
root@node1:~# docker node update --availability active node2
node2
root@node1:~# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
b57tzjj8jytnhmw32sy277i70    node2     Ready   Active
emit8i9n4tplyd29ewvta2usy *  node1     Ready   Active        Leader
```

node1に偏った状態になりました

```
root@node1:~# docker service ps test
NAME                 IMAGE         NODE   DESIRED STATE  CURRENT STATE           ERROR  PORTS
test.1.gqik60uihoh2  nginx:latest  node1  Running        Running 2 minutes ago
test.2.plgci5ln455x  nginx:latest  node1  Running        Running 36 seconds ago
```

`service update --force` でリフッシュしてリバランスさせてみます。

```
root@node1:~# docker service update --force test
test
root@node1:~# docker service ps test
NAME                 IMAGE         NODE   DESIRED STATE  CURRENT STATE          ERROR  PORTS
test.1.k4x3elvgegab  nginx:latest  node1  Running        Running 7 seconds ago
test.2.kx1kk3zehvaq  nginx:latest  node2  Running        Running 8 seconds ago
```

node1/node2にリバランスしてますね。

## docker service create --env-file

適当なenvファイルを用意します。

```
root@node1:~# vi test.env
root@node1:~# cat test.env
HOGE=hoge
FUGA=fuga
```

`--env-file` を指定してserviceを作ります。

```
root@node1:~#  docker service create --env-file test.env --name env_test nginx
3bfwb56dkfjsvahvkeehlo6kv
root@node1:~# docker service ps env_test
NAME                     IMAGE         NODE   DESIRED STATE  CURRENT STATE         ERROR  PORTS
env_test.1.08pyx4dkwe6c  nginx:latest  node2  Running        Running 1 second ago
```

ちょっとコンテナの中で環境変数を見てみます。

```
root@node2:~# docker ps
CONTAINER ID        IMAGE                                                                                COMMAND                  CREATED             STATUS              PORTS               NAMES
7c20ef03306e        nginx@sha256:9038d5645fa5fcca445d12e1b8979c87f46ca42cfb17beb1e5e093785991a639        "nginx -g 'daemon ..."   10 seconds ago      Up 9 seconds        80/tcp, 443/tcp     env_test.1.08pyx4dkwe6cr45ik2rab07s3
root@node2:~# docker exec -it 7c20ef03306e /bin/bash
root@7c20ef03306e:/# echo $HOGE
hoge
root@7c20ef03306e:/# echo $FUGA
fuga
```

ちゃんと渡されてますね。

## docker service ps --no-trunc
ちょっとわざと存在しないイメージ名を指定してservice createしてみます。

```
root@node1:~# docker service create --name piyo minamijoyo/hoge:latest
unable to pin image minamijoyo/hoge:latest to digest: errors:
denied: requested access to the resource is denied
unauthorized: authentication required

7cpsarjquhz6crpabjnq3jotp
```

なんだか認証エラーっぽいよくわからないエラーが出ました。 
`docker service ps` で見るとエラーメッセージが途中で切れています。

```
root@node1:~# docker service ps -a piyo
NAME                     IMAGE                   NODE   DESIRED STATE  CURRENT STATE                    ERROR                             PORTS
piyo.1.w2p0hsgdumgg      minamijoyo/hoge:latest  node1  Ready          Rejected less than a second ago  "No such image: minamijoyo/hog…"
 \_ piyo.1.pp9ngzgjn6li  minamijoyo/hoge:latest  node1  Shutdown       Rejected 5 seconds ago           "No such image: minamijoyo/hog…"
 \_ piyo.1.45el83wvoqm8  minamijoyo/hoge:latest  node1  Shutdown       Rejected 10 seconds ago          "No such image: minamijoyo/hog…"
 \_ piyo.1.3cl1epnuoman  minamijoyo/hoge:latest  node2  Shutdown       Rejected 15 seconds ago          "No such image: minamijoyo/hog…"
 \_ piyo.1.rk9u5u86pwjh  minamijoyo/hoge:latest  node1  Shutdown       Rejected 20 seconds ago          "No such image: minamijoyo/hog…"
```

この例だと先頭の `No such image: minamijoyo/hog…` でなんとなく雰囲気わかりますが、全文を見るには個別に `docker inspect` しないといけませんでした。

これが、 `--no-trunc` オプションを付けるとエラーの全文 `No such image: minamijoyo/hoge:latest` が見えるようになりました。ちょっとこの例だと分かりづらかったですが、serviceがうまく起動できないときにデバッグが捗るので、地味だけどうれしい。

```
root@node1:~# docker service ps -a --no-trunc piyo
NAME                     IMAGE                   NODE   DESIRED STATE  CURRENT STATE                    ERROR                                    PORTS
piyo.1.i3k9hy34f8kk      minamijoyo/hoge:latest  node2  Ready          Assigned less than a second ago                 
 \_ piyo.1.i12rv7ce5exx  minamijoyo/hoge:latest  node2  Shutdown       Rejected 3 seconds ago           "No such image: minamijoyo/hoge:latest"
 \_ piyo.1.w2p0hsgdumgg  minamijoyo/hoge:latest  node1  Shutdown       Rejected 8 seconds ago           "No such image: minamijoyo/hoge:latest"
 \_ piyo.1.pp9ngzgjn6li  minamijoyo/hoge:latest  node1  Shutdown       Rejected 13 seconds ago          "No such image: minamijoyo/hoge:latest"
 \_ piyo.1.45el83wvoqm8  minamijoyo/hoge:latest  node1  Shutdown       Rejected 18 seconds ago          "No such image: minamijoyo/hoge:latest"
 \_ piyo.1.3cl1epnuoman  minamijoyo/hoge:latest  node2  Shutdown       Rejected 23 seconds ago          "No such image: minamijoyo/hoge:latest"
```

## docker system df

`docker system df` というディスク使用量を簡単にチェックできるコマンドが増えました。

```
root@node1:~# docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              3                   2                   410.7 MB            224.4 MB (54%)
Containers          8                   1                   2 B                 0 B (0%)
Local Volumes       0                   0                   0 B                 0 B
```

内訳を出すには `-v` をつける

```
root@node1:~# docker system df -v
Images space usage:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE                SHARED SIZE         UNIQUE SIZE         CONTAINERS
nginx               latest              05a60462f8ba        2 weeks ago         181.5 MB            0 B                 181.5 MB            4
alpine              latest              baa5d63471ea        5 weeks ago         4.803 MB            0 B                 4.803 MB            4
tutum/curl          latest              01176385d84a        2 years ago         224.4 MB            0 B                 224.4 MB            0

Containers space usage:

CONTAINER ID        IMAGE                                                                           COMMAND                  LOCAL VOLUMES       SIZE                CREATED              STATUS                          NAMES
1b00b00dab7c        alpine                                                                          "echo hoge"              0                   0 B                 17 seconds ago       Exited (0) 17 seconds ago       admiring_einstein
c1524ac0883b        nginx@sha256:9038d5645fa5fcca445d12e1b8979c87f46ca42cfb17beb1e5e093785991a639   "nginx -g 'daemon ..."   0                   2 B                 About a minute ago   Up About a minute               hoge_web.1.tyepsp0wz953ng4a7yxd0zc7f
72b55401186a        nginx                                                                           "nginx -V"               0                   0 B                 5 minutes ago        Created                         small_ptolemy
e9b699272ec0        nginx                                                                           "nginx -V"               0                   0 B                 7 minutes ago        Created                         furious_lalande
f4af143e3c9d        alpine                                                                          "/bin/sh"                0                   0 B                 8 minutes ago        Created                         serene_lewin
fbf1ca0e64aa        alpine                                                                          "echo hoge"              0                   0 B                 9 minutes ago        Created                         evil_jang
ad5655d62262        alpine                                                                          "echo hoge"              0                   0 B                 9 minutes ago        Created                         drunk_curie
e53936b3beee        nginx@sha256:9038d5645fa5fcca445d12e1b8979c87f46ca42cfb17beb1e5e093785991a639   "nginx -g 'daemon ..."   0                   0 B                 5 hours ago          Exited (0) About a minute ago   hoge_web.1.ns6p315r7w86yri20wuoyy948

Local Volumes space usage:

VOLUME NAME         LINKS               SIZE
```

## docker system prune

docker runで　`--rm` 付け忘れて残っちゃったコンテナとか使われていない参照されていないImageやVolume、使われていないNetworkなどを一括でお掃除してくれる `docker system prune` というコマンドができました。

```
root@node1:~# docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              3                   2                   410.7 MB            224.4 MB (54%)
Containers          8                   1                   2 B                 0 B (0%)
Local Volumes       0                   0                   0 B                 0 B
```

```
root@node1:~# docker system prune
WARNING! This will remove:
        - all stopped containers
        - all volumes not used by at least one container
        - all networks not used by at least one container
        - all dangling images
Are you sure you want to continue? [y/N] y
Deleted Containers:
1b00b00dab7c1d39821bf35f653cb34be4e560dcb52ad426decb94c80a2e7a21
72b55401186aaf0283653227c66eaa2f3c5ba0885fb05a78b88b249c72203e6b
e9b699272ec03d65a6831d80049e5d72aa1ed7d6de0b9211e015c1d30ccfd637
f4af143e3c9d987b92128659f0a9070e0470905fb1fa7f66396fa19ca0bad06f
fbf1ca0e64aae36b37706768eb6c0613ff98862e841fdf5fcffc38f594ecff7c
ad5655d6226234676694450f24047e3f7b874e139dbfac3833e3f20074c12474
e53936b3beeee06ae464ca625f42d81064c2d45e8dfdcf7e064722c848a66032

Deleted Networks:
fuga

Total reclaimed space: 0 B
```

```
root@node1:~# docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              3                   1                   410.7 MB            229.2 MB (55%)
Containers          1                   1                   2 B                 0 B (0%)
Local Volumes       0                   0                   0 B                 0 B
```

それぞれ個別に削除する `docker {container,image,volume,network} prune` コマンドもある。

## docker secret

機密情報をコンテナ内に安全に受け渡しするために `docker secret` という仕組みができました。環境変数だとinspectすると見えちゃうしね。内部的には現状swarmに依存しているので今のところswarm mode以外では使えないようです。

`docker secret create` で作ります。

```
root@node1:~# echo "top_secret" | docker secret create ssh-dev
hebw7cvza4lk2gzprdljmvvhv
```

`docker service create --secret` で渡す。

```
root@node1:~# docker service create --name nginx --secret ssh-dev nginx
5sn2d8c0aljkxwfg0antdntf4
```

コンテナの中で見てみる。

```
root@node1:~# docker ps
CONTAINER ID        IMAGE                                                                           COMMAND                  CREATED             STATUS              PORTS               NAMES
f9ff7e041386        nginx@sha256:9038d5645fa5fcca445d12e1b8979c87f46ca42cfb17beb1e5e093785991a639   "nginx -g 'daemon ..."   39 seconds ago      Up 33 seconds       80/tcp, 443/tcp     nginx.1.l4l7c0s1efvb0aj5q4iudb8sx
root@node1:~# docker exec -it f9ff7e041386 /bin/bash
root@f9ff7e041386:/# cat /run/secrets/ssh-dev
top_secret
```

配置したいファイル名を変更したい場合は、 `--secret` で渡すときに `target=` でファイル名を指定できます。

```
root@node1:~# docker service create --name nginx --secret source=ssh-dev,target=id_rsa,uid=1000,gid=1000,mode=0400 nginx
5jsuv5e89crc4esafsh948gjn
```

```
root@node2:~# docker ps
CONTAINER ID        IMAGE                                                                                COMMAND                  CREATED             STATUS              PORTS               NAMES
0e3fc7cf18bd        nginx@sha256:9038d5645fa5fcca445d12e1b8979c87f46ca42cfb17beb1e5e093785991a639        "nginx -g 'daemon ..."   12 seconds ago      Up 11 seconds       80/tcp, 443/tcp     nginx.1.z2mw5h7y7olfbl7hsh2ybw5hm
root@node2:~# docker exec -it 0e3fc7cf18bd /bin/bash
root@0e3fc7cf18bd:/# cat /run/secrets/id_rsa
top_secret
```

# まとめ
ざーっと気になる変更点と新機能を見てきましたが、Docker1.13には痒いところに手が届く多くの改善が含まれています。swarmのdocker-compose.yml対応はまだ出来たてホヤホヤ感がありますが、Docker本体にクラスタを管理する仕組みがどんどん拡充されてきて今後が楽しみで仕方がない。

この記事は[CrowdWorks Advent Calendar 2016](http://qiita.com/advent-calendar/2016/crowdworks) の1日目の記事でした。明日は[@h3_poteto](http://qiita.com/h3_poteto)の「Docker swarmで構築する社内heroku: yadockeri」の予定です。