背景
個人のサービスをdockerで本番運用を行うにあたって
- コンテナアップデート時のダウンタイムは無くしたい
- 1つのサーバーで完結したい(別途ロードバランサーを用意したくない)
みたいなことを考えていたのですが、docker swarmを利用すると、とても簡単に実現できたので共有したいと思います。
検証環境
Docker version 17.10.0-ce, build f4ffd25
docker swarm の作成
managerのnodeが1つだけある環境を用意します。
$ docker swarm init --advertise-addr="リモートのIPアドレス"
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
qjdzkq17bxva02am04rou51dw * digitalocean Ready Active Leader
Serviceの作成
1つのサービスを2つのコンテナ(レプリカ)で作成します。
$ docker service create --name demo --replicas 2 --update-delay 10s -p 8080:8080 hashicorp/http-echo -listen=:8080 -text="demo-1"
今回の検証にはhashicorp/http-echo
のイメージを使用しています。
これは起動時に引数で渡した文字列を表示してくれるWebサーバーのコンテナです。
https://hub.docker.com/r/hashicorp/http-echo/
Service起動の確認
--replicas 2
を指定したのでコンテナが2つ作成できています。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a0dcff10b6c8 hashicorp/http-echo:latest "/http-echo -text=..." 10 hours ago Up 10 hours 5678/tcp demo.3.9zba9ygmdnjo764rt8fgprcip
baffe41b305d hashicorp/http-echo:latest "/http-echo -text=..." 24 hours ago Up 24 hours 5678/tcp demo.2.ydki5edzc2r1henjtw343el6f
$ curl http://サーバーIPアドレス:8080/
demo-1
Serviceのアップデート
docker service update
コマンドを利用すると、各コンテナを順にローリングアップデートしてくれます。アップデート中も一方のコンテナが起動しているので、サービスを継続しながらのアップデートが可能です。
起動時とは引数を変えてイメージをアップデートします。
$ docker service update --image hashicorp/http-echo --args "-text="demo-2" -listen=:8080" demo
demo
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service converged
外部からウォッチしながらアップデートをすると次のようなログになります。
$ while true; do curl http://サーバーIPアドレス:8080/; sleep 1s; done
demo-1
demo-1
demo-1
demo-2 ←片方のコンテナがアップデート完了
demo-1
demo-2
demo-1
demo-2
demo-1
demo-2
demo-1
demo-2
demo-1
demo-2
demo-1
demo-2
demo-2 ←両方のコンテナがアップデート完了
demo-2
demo-2
※今回はService作成時に--update-delay 10s
を指定しているので、各コンテナのアップデートには10秒の間隔が空きます。
アップデートのロールバック
docker swarm rollback
コマンドを使えば、デプロイ後に問題が見つかった場合も、サービスを1世代前に戻すことができます。
$ docker service rollback demo
rollback: manually requested rollback
overall progress: rolling back update: 2 out of 2 tasks
1/2: running [> ]
2/2: running [> ]
verify: Service converged
$ curl http://サーバーIPアドレス:8080/
demo-1
rollbackコマンドは、Docker 17.09.0-ce以降で利用できます
https://docs.docker.com/release-notes/docker-ce/
参考
Apply rolling updates to a service
https://docs.docker.com/engine/swarm/swarm-tutorial/rolling-update/