👢

Docker Swarmモードを試す

2025/02/08に公開

概要

Docker Swarmモードを試します。

参考
https://docs.docker.com/engine/swarm/

環境

Raspberry Pi 上の KVM で Docker12 を動かし、その中で Docker を動かす。
Dockerのインストール等の準備については割愛。

Manager node

マネージャーノードを動かす。
自分のIPアドレスを指定して初期化する。

$ sudo docker swarm init --advertise-addr 192.168.11.11
Swarm initialized: current node (sbcsogqf801wvr2lsh4m7mggc) is now a manager.

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

    docker swarm join --token SWMTKN-1-1ll3ai2i7foe89icduye1id8nhorcylon2x5hiz2bgstfhcewc-9mnu43adxjp567a1c0xgm53hq 192.168.11.11:2377

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

確認

$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
sbcsogqf801wvr2lsh4m7mggc *   test1      Ready     Active         Leader           27.5.1

Add worker nodes

ワーカーノードを追加する

$ sudo docker swarm join --token SWMTKN-1-1ll3ai2i7foe89icduye1id8nhorcylon2x5hiz2bgstfhcewc-9mnu43adxjp567a1c0xgm53hq 192.168.11.11:2377
This node joined a swarm as a worker.

マネージャーノードで確認。
(Swarmの管理コマンドはマネージャーノードでしか実行できない)

$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
sbcsogqf801wvr2lsh4m7mggc *   test1      Ready     Active         Leader           27.5.1
ece1l1kqp2om2elwnw4hhn7rr     test2      Ready     Active                          27.5.1
h6sbsrqknih6ayb1jarfyl04q     test3      Ready     Active                          27.5.1

サービスのデプロイ

レプリカ数 =1 で nginx のコンテナを起動してみる。
(マネージャーノードで実行)

$ sudo docker service create --replicas 1 --name nginx-test -p 80:80 nginx
zoa52ht9v0a8fjmjh2972a1y9
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service zoa52ht9v0a8fjmjh2972a1y9 converged

確認。

$ sudo docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
zoa52ht9v0a8   nginx-test   replicated   1/1        nginx:latest   *:80->80/tcp

$ sudo docker service ps nginx-test
ID             NAME           IMAGE          NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
a8dr62xk68mj   nginx-test.1   nginx:latest   test1     Running         Running 3 minutes ago

$ sudo docker service inspect --pretty nginx-test
                                                                                                                                                                                                        
ID:             jmjh2972a1y9
Name:           nginx-test
Service Mode:   Replicated
 Replicas:      1
Placement:
UpdateConfig:
 Parallelism:   1
 On failure:    pause
 Monitoring Period: 5s
 Max failure ratio: 0
 Update order:      stop-first
RollbackConfig:
 Parallelism:   1
 On failure:    pause
 Monitoring Period: 5s
 Max failure ratio: 0
 Rollback order:    stop-first
ContainerSpec:
 Image:         nginx:latest@sha256:0a399eb16751829e1af26fea27b20c3ec28d7ab1fb72182879dcae1cca21206a
 Init:          false
Resources:
Endpoint Mode:  vip
Ports:
 PublishedPort = 80
  Protocol = tcp
  TargetPort = 80
  PublishMode = ingress

実行されているノードで確認
(ここではマネージャーノードだけど、Swarm管理ではないDockerコマンドはワーカーノードで実行可能)

$ sudo docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
a7e28d40037f   nginx:latest   "/docker-entrypoint._"   4 minutes ago   Up 4 minutes   80/tcp    nginx-test.1.a8dr62xk68mjrznz7h31c2ayd

スケーリング

レプリカ数を2に増やす。マネージャーノードで実行

$ sudo docker service scale nginx-test=2
nginx-test scaled to 2
overall progress: 2 out of 2 tasks
1/2: running   [==================================================>]
2/2: running   [==================================================>]
verify: Service nginx-test converged

確認

$ sudo docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
zoa52ht9v0a8   nginx-test   replicated   2/2        nginx:latest   *:80->80/tcp

$ sudo docker service ps nginx-test
ID             NAME           IMAGE          NODE      DESIRED STATE   CURRENT STATE                ERROR     PORTS
a8dr62xk68mj   nginx-test.1   nginx:latest   test1     Running         Running 7 minutes ago
u2j3a9jo6kst   nginx-test.2   nginx:latest   test2     Running         Running about a minute ago

実行されているノードで確認

$ sudo docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED              STATUS              PORTS     NAMES
1f1631b840c1   nginx:latest   "/docker-entrypoint._"   About a minute ago   Up About a minute   80/tcp    nginx-test.2.u2j3a9jo6kstk6qk4k94so0kg

レプリカ数を1に減らす

$ sudo docker service scale nginx-test=1
nginx-test scaled to 1
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service nginx-test converged

確認

$ sudo docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
zoa52ht9v0a8   nginx-test   replicated   1/1        nginx:latest   *:80->80/tcp

$ sudo docker service ps nginx-test
ID             NAME           IMAGE          NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
a8dr62xk68mj   nginx-test.1   nginx:latest   test1     Running         Running 9 minutes ago

サービス全削除

$ sudo docker service rm nginx-test
nginx-test
$ sudo docker service inspect nginx-test
[]
Status: Error: no such service: nginx-test, Code: 1

ノード退避

テストのためレプリカ数3 でnginx を動かしておく。

$ sudo docker service create --replicas 3 --name nginx-test -p 80:80 nginx
o5clx0cyrxjyfgtk0jqd8kobn
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Service o5clx0cyrxjyfgtk0jqd8kobn converged

$ sudo docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
o5clx0cyrxjy   nginx-test   replicated   3/3        nginx:latest   *:80->80/tcp

$ sudo docker service ps nginx-test
ID             NAME           IMAGE          NODE      DESIRED STATE   CURRENT STATE                ERROR     PORTS
r24o7jlzt6d0   nginx-test.1   nginx:latest   test2     Running         Running about a minute ago
546o0iloiiqe   nginx-test.2   nginx:latest   test3     Running         Running about a minute ago
jfrfec6fglw7   nginx-test.3   nginx:latest   test1     Running         Running about a minute ago

退避前の状態

$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
sbcsogqf801wvr2lsh4m7mggc *   test1      Ready     Active         Leader           27.5.1
ece1l1kqp2om2elwnw4hhn7rr     test2      Ready     Active                          27.5.1
h6sbsrqknih6ayb1jarfyl04q     test3      Ready     Active                          27.5.1
$ sudo docker node inspect --pretty test3
ID:                     h6sbsrqknih6ayb1jarfyl04q
Hostname:               test3
Joined at:              2025-01-31 12:19:14.298644413 +0000 utc
Status:
 State:                 Ready
 Availability:          Active
 Address:               192.168.11.14
Platform:
 Operating System:      linux
 Architecture:          aarch64
Resources:
 CPUs:                  2
 Memory:                970.7MiB
Plugins:
 Log:           awslogs, fluentd, gcplogs, gelf, journald, json-file, local, splunk, syslog
 Network:               bridge, host, ipvlan, macvlan, null, overlay
 Volume:                local
Engine Version:         27.5.1
TLS Info:
 TrustRoot:
 略

test3 を退避してみる

$ sudo docker node update --availability drain test3
test3

nginxコンテナの確認

$ sudo docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
o5clx0cyrxjy   nginx-test   replicated   3/3        nginx:latest   *:80->80/tcp

$ sudo docker service ps nginx-test
ID             NAME               IMAGE          NODE      DESIRED STATE   CURRENT STATE             ERROR     PORTS
r24o7jlzt6d0   nginx-test.1       nginx:latest   test2     Running         Running 4 minutes ago
i00d9zpxvm2p   nginx-test.2       nginx:latest   test1     Running         Running 29 seconds ago
546o0iloiiqe    \_ nginx-test.2   nginx:latest   test3     Shutdown        Shutdown 30 seconds ago
jfrfec6fglw7   nginx-test.3       nginx:latest   test1     Running         Running 4 minutes ago

ノードの確認

$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
sbcsogqf801wvr2lsh4m7mggc *   test1      Ready     Active         Leader           27.5.1
ece1l1kqp2om2elwnw4hhn7rr     test2      Ready     Active                          27.5.1
h6sbsrqknih6ayb1jarfyl04q     test3      Ready     Drain                           27.5.1

ノード復旧

退避したノードを復旧する

$ sudo docker node update --availability active test3
test3
$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
sbcsogqf801wvr2lsh4m7mggc *   test1      Ready     Active         Leader           27.5.1
ece1l1kqp2om2elwnw4hhn7rr     test2      Ready     Active                          27.5.1
h6sbsrqknih6ayb1jarfyl04q     test3      Ready     Active                          27.5.1

ノードを復旧しても自動でリバランスされない。

$ sudo docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
o5clx0cyrxjy   nginx-test   replicated   3/3        nginx:latest   *:80->80/tcp

$ sudo docker service ps nginx-test
ID             NAME               IMAGE          NODE      DESIRED STATE   CURRENT STATE            ERROR     PORTS
r24o7jlzt6d0   nginx-test.1       nginx:latest   test2     Running         Running 7 minutes ago
i00d9zpxvm2p   nginx-test.2       nginx:latest   test1     Running         Running 4 minutes ago
546o0iloiiqe    \_ nginx-test.2   nginx:latest   test3     Shutdown        Shutdown 4 minutes ago
jfrfec6fglw7   nginx-test.3       nginx:latest   test1     Running         Running 7 minutes ago

サービスへのアクセス

仮想ロードバランサ的なものが働いており、Swarmに参加しているノードのどのアドレスでもサービスにアクセスできる。

$ curl -I 192.168.11.11
HTTP/1.1 200 OK
Server: nginx/1.27.3
Date: Fri, 31 Jan 2025 12:51:26 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 26 Nov 2024 15:55:00 GMT
Connection: keep-alive
ETag: "6745ef54-267"
Accept-Ranges: bytes
$ curl -I 192.168.11.12
HTTP/1.1 200 OK
Server: nginx/1.27.3
Date: Fri, 31 Jan 2025 12:51:29 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 26 Nov 2024 15:55:00 GMT
Connection: keep-alive
ETag: "6745ef54-267"
Accept-Ranges: bytes
$ curl -I 192.168.11.14
HTTP/1.1 200 OK
Server: nginx/1.27.3
Date: Fri, 31 Jan 2025 12:53:03 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 26 Nov 2024 15:55:00 GMT
Connection: keep-alive
ETag: "6745ef54-267"
Accept-Ranges: bytes

ノードの管理

$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
nl2ywxl6kp1viic7xy2hhluvp *   test1      Ready     Active         Leader           27.5.1
nez6ry9m51s0b43m1hcc7r8ms     test2      Ready     Active                          27.5.1
o9ioezxr2k7fng5xjnlnlrex8     test3      Ready     Active                          27.5.1

test3をマネージャーノードへ昇格してみる

$ sudo docker node promote test3
Node test3 promoted to a manager in the swarm.

昇格したtest3でSwarm管理コマンドが実行できることを確認

$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION                                                                                                                nl2ywxl6kp1viic7xy2hhluvp     test1      Ready     Active         Leader           27.5.1
nez6ry9m51s0b43m1hcc7r8ms     test2      Ready     Active                          27.5.1
o9ioezxr2k7fng5xjnlnlrex8 *   test3      Ready     Active         Reachable        27.5.1

$ sudo docker node inspect --pretty test3
ID:                     o9ioezxr2k7fng5xjnlnlrex8
Hostname:               test3
Joined at:              2025-02-07 21:34:46.7371155 +0000 utc
Status:
 State:                 Ready
 Availability:          Active
 Address:               192.168.11.13
Manager Status:
 Address:               192.168.11.13:2377
 Raft Status:           Reachable
 Leader:                No
Platform:
 Operating System:      linux
 Architecture:          aarch64                                                                                                                                                                                  Resources:
 CPUs:                  2
 Memory:                970.7MiB
Plugins:
 Log:           awslogs, fluentd, gcplogs, gelf, journald, json-file, local, splunk, syslog
 Network:               bridge, host, ipvlan, macvlan, null, overlay
 Volume:                local
Engine Version:         27.5.1
TLS Info:

test1をワーカーノードへ降格してみる

$ sudo docker node demote test1
Manager test1 demoted in the swarm.
$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
nl2ywxl6kp1viic7xy2hhluvp     test1      Ready     Active                          27.5.1
nez6ry9m51s0b43m1hcc7r8ms     test2      Ready     Active                          27.5.1
o9ioezxr2k7fng5xjnlnlrex8 *   test3      Ready     Active         Leader           27.5.1

$ sudo docker node inspect --pretty test1
ID:                     nl2ywxl6kp1viic7xy2hhluvp
Hostname:               test1
Joined at:              2025-02-07 21:34:17.019456947 +0000 utc
Status:
 State:                 Ready
 Availability:          Active
 Address:               192.168.11.11
Platform:
 Operating System:      linux
 Architecture:          aarch64
Resources:
 CPUs:                  2
 Memory:                970.7MiB
Plugins:
 Log:           awslogs, fluentd, gcplogs, gelf, journald, json-file, local, splunk, syslog
 Network:               bridge, host, ipvlan, macvlan, null, overlay
 Volume:                local
Engine Version:         27.5.1
TLS Info:

スタック

動いているサービスをいったん終了

$ sudo docker service ls
ID             NAME         MODE         REPLICAS   IMAGE          PORTS
lvdja2gyqsoz   nginx-test   replicated   3/3        nginx:latest   *:80->80/tcp

$ sudo docker service ps nginx-test
ID             NAME               IMAGE          NODE      DESIRED STATE   CURRENT STATE             ERROR     PORTS
vhi76gclnszm   nginx-test.1       nginx:latest   test2     Running         Running 11 minutes ago
8ojcalnihxw7   nginx-test.2       nginx:latest   test1     Running         Running 11 minutes ago
ly5y93o5zkc8    \_ nginx-test.2   nginx:latest   test3     Shutdown        Shutdown 37 minutes ago
49t116o6f1qr   nginx-test.3       nginx:latest   test1     Running         Running 11 minutes ago

$ sudo docker service rm nginx-test
nginx-test

$ sudo docker service ls
ID        NAME      MODE      REPLICAS   IMAGE     PORTS

$ sudo docker service inspect nginx-test
[]
Status: Error: no such service: nginx-test, Code: 1

以下の内容で compose.yaml を準備

compose.yaml
version: "3"
services:
  nginx-test:
    image: nginx
    deploy:
      replicas: 3
      restart_policy:
        condition: on-failure
    ports:
      - "80:80"

スタックを作成する

$ sudo docker stack deploy --compose-file compose.yaml nginx-stack
Since --detach=false was not specified, tasks will be created in the background.
In a future release, --detach=false will become the default.
Creating network nginx-stack_default
Creating service nginx-stack_nginx-stack

結果を確認

$ sudo docker stack ls
NAME          SERVICES
nginx-stack   1

$ sudo docker stack services nginx-stack
ID             NAME                      MODE         REPLICAS   IMAGE          PORTS
bqhkpnm16knv   nginx-stack_nginx-stack   replicated   3/3        nginx:latest   *:80->80/tcp

$ sudo docker stack ps nginx-stack
ID             NAME                        IMAGE          NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
dwb9pm647j7t   nginx-stack_nginx-stack.1   nginx:latest   test2     Running         Running 2 minutes ago
qc6y2dj6k1wd   nginx-stack_nginx-stack.2   nginx:latest   test1     Running         Running 2 minutes ago
rsnfl60uhto7   nginx-stack_nginx-stack.3   nginx:latest   test3     Running         Running 2 minutes ago

Swarmの観点で確認

$ sudo docker service ls
ID             NAME                      MODE         REPLICAS   IMAGE          PORTS
bqhkpnm16knv   nginx-stack_nginx-stack   replicated   3/3        nginx:latest   *:80->80/tcp

$ sudo docker service ps nginx-stack_nginx-stack
ID             NAME                        IMAGE          NODE      DESIRED STATE   CURRENT STATE           ERROR     PORTS
dwb9pm647j7t   nginx-stack_nginx-stack.1   nginx:latest   test2     Running         Running 7 minutes ago
qc6y2dj6k1wd   nginx-stack_nginx-stack.2   nginx:latest   test1     Running         Running 7 minutes ago
rsnfl60uhto7   nginx-stack_nginx-stack.3   nginx:latest   test3     Running         Running 7 minutes ago

スタックの終了

$ sudo docker stack rm nginx-stack
Removing service nginx-stack_nginx-stack
Removing network nginx-stack_default
$ sudo docker stack ls
NAME      SERVICES
GitHubで編集を提案

Discussion