Docker Swarm環境を構築したり、DockerのWebGUI管理アプリをセットアップしたり

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

この記事ではタイトルの通り、コンテナオーケストレーションツールの1つであるSwarm環境を構築してみたり、Docker/Swarm/k8s等環境をWebブラウザで操作するためのアプリケーションであるportainerのセットアップを行い、どうせならService（≒Swarmでいうコンテナ的なイメージ。雑な表現ですが）をCUI/GUI双方でデプロイしてみようと思います。

# 環境
イメージとしては以下となります。
Proxmox VEと呼ばれる仮想化プラットフォーム上にUbuntu22.04で立ち上げたVMを3台用意。
1台をmaster、残り2台をworkerとしdockerクラスタ環境を構築していきたいと思います。

※コンテナのクラスタと考えるとk8sが第一候補になりますが、あれは少々大規模すぎます。
　プライベートアプリ本番/開発環境程度であればSwarmも候補になりえるのでは？と思いました。
※Swarmとは「群れ」の意味らしいです。だからDocker Swarmのイラストはクジラさんが
　たくさんいるやつなんですね・・・！
![docker-ページ14.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/bd15c93c-df5a-0997-271d-4bbe7ca270b1.png)

# Docker Swarm環境構築
## masterの構築
まずmasterの設定をしていきます。
masterの現環境は以下
コンテナもネットワークの状態もデフォルトです。
```
root@docker:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
root@docker:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
50269d80052b   bridge    bridge    local
e80bd3a263ec   host      host      local
93abcdf649c5   none      null      local
```

次にdocker infoコマンドを叩いてSwarmがinactiveであることを確認します。
```
root@docker:~# docker info

 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 2806fc1057397dbaeefbea0e4e17bddfbd388f38
 runc version: v1.1.5-0-gf19387a
 init version: de40ad0
 Security Options:
```

docker swarmを有効化？するにはdocker swarm initコマンドを実行します。
実際に試してみたら以下のようなエラーを吐かれました。
とりあえずdocker swarm leave（≒Swarmクラスタから抜けろ）ということっぽいですね。
```
root@docker:~# docker swarm init
Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one.
```

docker swarm leaveコマンドだけだとさらにエラーを返されることもあったため、--forceオプションを指定し、強制的にleaveします。
そのあとに再度initを試みるのですが、、、駄目でした汗
```
root@docker:~# docker swarm leave --force
Node left the swarm.
root@docker:~# docker swarm init
Error response from daemon: error updating cluster settings: rpc error: code = DeadlineExceeded desc = context deadline exceeded
```

このエラーは/etc/docker/swarm.jsonファイルに以下を追加することで解消できました。
このjsonファイルはデフォルトでカラでした。
```
root@docker:~# vi /etc/docker/daemon.json
root@docker:~# cat /etc/docker/daemon.json
{
    "live-restore": false
}
root@docker:~# systemctl restart docker
```

再度initを試みたところいけました！
出力内の"To add a worker to this swarm, run the following command:"以降のコマンドは
後ほど使いますので控えておきましょう。
```
root@docker:~# docker swarm init
Swarm initialized: current node (624so5sshxf30h6bgde3mr9kl) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0mspavxn7ok3a6ee833ru0rxpdwqper8tnkuxxcx00ni4v9l09-30f2ondatog3wu9c400444ikg 192.168.2.177:2377
    
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
```

docker infoを改めてみてみるとSwarmの欄がactiveと変わっていることが確認できるかと思います。
```
root@docker:~# docker info

Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: active
  NodeID: 624so5sshxf30h6bgde3mr9kl
  Is Manager: true
  ClusterID: o6czpv3l3noowc3lh9zp0xkcx
  Managers: 1
  Nodes: 3
  Default Address Pool: 10.0.0.0/8
```

## workerの構築
続いてworkerの設定をしていきます。
ここでは叩いたコマンドだけ記載いたします。
それぞれのノードの最後に叩いている"docker swarm join~"はmaster側で"docker swarm init"を実行した後に出てくる"To add a worker to this swarm, run the following command:"の後に記載されているコマンドになります。

- worker01
```
root@swarm-worker01:~# apt-get update
root@swarm-worker01:~# apt-get upgrade
root@swarm-worker01:~# apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
root@swarm-worker01:~# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
root@swarm-worker01:~# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
root@swarm-worker01:~# apt-get update
root@swarm-worker01:~# apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
root@swarm-worker01:~# docker --version
Docker version 23.0.4, build f480fb1
root@swarm-worker01:~# vi /etc/docker/daemon.json
root@swarm-worker01:~# systemctl restart docker
root@swarm-worker01:~# docker swarm join --token SWMTKN-1-0mspavxn7ok3a6ee833ru0rxpdwqper8tnkuxxcx00ni4v9l09-30f2ondatog3wu9c400444ikg 192.168.2.177:2377
This node joined a swarm as a worker.
```

- worker02
```
root@swarm-worker02:~# apt-get update
root@swarm-worker02:~# apt-get upgrade
root@swarm-worker02:~# apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
root@swarm-worker02:~# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
root@swarm-worker02:~# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
root@swarm-worker02:~# apt-get update
root@swarm-worker02:~# apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
root@swarm-worker02:~# docker --version
Docker version 23.0.4, build f480fb1
root@swarm-worker02:~# vi /etc/docker/daemon.json
root@swarm-worker02:~# systemctl restart docker
root@swarm-worker02:~# docker swarm join --token SWMTKN-1-0mspavxn7ok3a6ee833ru0rxpdwqper8tnkuxxcx00ni4v9l09-30f2ondatog3wu9c400444ikg 192.168.2.177:2377
This node joined a swarm as a worker.
```

## クラスタ確認

docker node lsコマンドを実行し、今回の場合計3台の内容が出力されていればクラスタ化成功です。
```
root@docker:~# docker node ls
ID                            HOSTNAME         STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
624so5sshxf30h6bgde3mr9kl *   docker           Ready     Active         Leader           23.0.3
ru8v94326h4pdghg0h1vifljy     swarm-worker01   Ready     Active                          23.0.4
pnmvavvon0hfrciinwn7w4pe3     swarm-worker02   Ready     Active                          23.0.4
```

docker network lsコマンドを叩いてみるとdriverがoverlayとなっているものとかが出来ていますね。
このあたりの検証は今後・・・
```
root@docker:~# docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
92d578e12a26   bridge            bridge    local
da8e681f4aa2   docker_gwbridge   bridge    local
e80bd3a263ec   host              host      local
5d0wz7me1k3q   ingress           overlay   swarm
93abcdf649c5   none              null      local
```

# portainer環境を構築

読み方がわかりませんが「ポーテナー」ですかね？
以下が公式サイトのようです。

https://www.portainer.io/

これがあることでdocker/swarm/k8s環境をGUIで操作・管理することができるようです。
これを構築してみようと思います。
とは言いつつ、dockerイメージがすでにあるので、これをpullしてデプロイするだけですけどね笑

以下のコマンドを実行します
```
root@docker:~# docker volume create portainer_data
portainer_data
root@docker:~# docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
Unable to find image 'portainer/portainer-ce:latest' locally
latest: Pulling from portainer/portainer-ce
772227786281: Pull complete
96fd13befc87: Pull complete
5171176db7f2: Pull complete
a143fdc4fa02: Pull complete
b622730c7bdc: Pull complete
69dd1305b74e: Pull complete
49818993c243: Pull complete
a1250f206ea5: Pull complete
54f8a26a4394: Pull complete
0e4b8aa1bb85: Pull complete
4f4fb700ef54: Pull complete
Digest: sha256:45104bb2ecbc7c24de937b4c43f87b85c9c7dd46924d27203c2aa2a613f78322
Status: Downloaded newer image for portainer/portainer-ce:latest
8240d0af95a3a994a408f99da8e282a21f6134dae02ec5a7ccb966e56af9701d
root@docker:~# docker ps
CONTAINER ID   IMAGE                    COMMAND        CREATED         STATUS         PORTS                                                                                            NAMES
8240d0af95a3   portainer/portainer-ce   "/portainer"   3 minutes ago   Up 3 minutes   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp, 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp, 9443/tcp   portainer
```

コンテナをデプロイできましたらWebブラウザを用意してアクセスします。
URLは"http://"ホストのIPアドレス":9000"となります。
アクセスできると以下のようにパスワードを求められるので、任意のものを入力し、Create userを押下します。![image (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/a4ee3b97-0466-2c20-f965-70f7c2809c39.png)

うまくいくといかのような画面が表示されるかと思います。
![image (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/a41aae77-a75f-7f0f-f073-a907dd3e2ed7.png)

※もし以下のような画面が出てきてしまった場合はportainerコンテナをstop→startしてみてください。
![image (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/7fc36dab-dc44-6c26-3281-8691f0d992cc.png)

Homeのlocal内にあるLive connectを押下します。
![image (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/4a9cfa54-5d2e-94fe-2c1b-c2b252e8bced.png)

コンテナが1件立ち上がっていることがわかりますね。
これはこのportainerコンテナ自身のことです。
![image (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/b5fc2359-085f-083d-bbb7-6178e479334d.png)

networkもすべて見れていように見えます。
![image (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/1753dab3-5b6f-69fd-2e9e-1706c54be713.png)

# Swarmのserviceをデプロイする。
最後にSwarmのserviceをCUI/GUI双方で試してみたいと思います
まずはCUI。問題なく行けてそうですね。
```
root@docker:~# docker service create --replicas 3 --name nginx nginx:latest
q3mg1bd2cjq125n8evhu2fsv2
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Service converged

root@docker:~# docker service ps nginx
ID             NAME      IMAGE          NODE             DESIRED STATE   CURRENT STATE                ERROR     PORTS
7cjbdf9htcgw   nginx.1   nginx:latest   swarm-worker02   Running         Running about a minute ago
nwbn4sewf7ug   nginx.2   nginx:latest   docker           Running         Running 5 minutes ago
g7t4p8ketaer   nginx.3   nginx:latest   swarm-worker01   Running         Running about a minute ago
```

GUIからもこれが確認できました。
![image (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/e02d0a85-385f-d6c8-b2e6-ce51398a0309.png)
![image (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/4cecad13-0e1a-4612-5128-a7a77f8824fb.png)



続いてGUI。
Add serviceを押下します。
![image (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/2989618c-32a9-1be5-5e47-3f25b65c9493.png)

今回は以下の設定で試してみます。
入力が出来たら左下のCreate the serviceを押下します。
![image (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/779bec2e-141c-a147-dc01-3f36f89385bd.png)

デプロイには少々時間がかかるかもしれませんが出来ました！
![image (18).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/091d3b58-31ca-c62c-19a3-49fad3258e28.png)
![image (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/0ee38dd0-0153-c96e-506d-a041fae65783.png)

最後にざっくり今の状態をイメージ化します。
serviceやnetwork周りの検証は今後確認していきます。
![docker-ページ15.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/da2e44b7-bc2f-df46-7741-64f2f1e8e769.png)