docker composeアプリをubuntu内でサービス化する

## 1. 背景
wikiとして活用しているアプリをdocker composeで立ち上げているのですが、長期間同じコンテナを使い続けると、ディスクが徐々に逼迫してくるという状態に陥っており、その度に、`docker compose down`, `docker compose up`で立ち上げ直していました。
（ディスクフルの原因はおそらく、wikiとして利用しているOSSのキャッシュ周り）

ディスクフルになるとwikiが使えない、かつ、手動でメンテナンスするのは辛いのでサービス化により解消を試みたという話です！

## 2. 前提
wikiを立ち上げている環境情報は以下の通りです。
 - サーバー：`Amazon EC2`
 - サーバー起動時間：`平日昼間（=日時で停止・起動される）`
 - OS：`Ubuntu 22.04.2 LTS`
 - Docker ver：`24.0.2`
 - Docker Compose ver：`v2.18.1`

docker-compose.ymlにて、`restart: unless-stopped`の設定を入れているため、サーバー停止・起動に伴い、コンテナが停止・起動されていました。

なお、必要なデータは全てvolumes指定で永続化させているので、compose down/upでコンテナが再作成されても問題ない設定になっています。

**永続化させてないデータはdown/upで吹っ飛ぶので注意です！！！**

## 3. サービス化
サーバー内ではwikiが動作中なので、まずはwikiを止めます。
```
# cd /mnt/wiki
# ls -l docker-compose.yml
-rw-r--r-- 1 root root 3022 Apr  8 13:38 docker-compose.yml
# docker compose down
```
サーバーの停止・起動に応じて勝手にコンテナを立ち上げないよう再起動ポリシーを変更します。
```
# vi docker-compose.yml

restart: unless-stopped
↓ ポリシーを変更
restart: on-failure:3
```
wikiサービスはdockerサービス起動後に起動させるため、事前にdockerのサービス識別子を確認しておきます。
```
# systemctl list-units --type=service --all | head -1; systemctl list-units --type=service --all | grep docker
  UNIT                                            LOAD      ACTIVE   SUB     DESCRIPTION
  docker.service                                  loaded    active   running Docker Application Container Engine
```
dockerコマンドの所在も確認しておきます。
```
# which docker
/usr/bin/docker
```
wikiのサービス定義を作成します。
```
# vi /etc/systemd/system/wiki_docker_compose.service
```
記述内容は以下。
```
[Unit]
Description=wiki docker-compose service
After=docker.service ← ★dockerサービスの識別子★

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/mnt/wiki ← ★docker-compose.ymlの格納場所★ 
ExecStart=/usr/bin/docker compose up -d ← ★dockerコマンドの所在に合わせてフルパスで指定★
ExecStop=/usr/bin/docker compose down ← ★dockerコマンドの所在に合わせてフルパスで指定★
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target
```
systemdにサービスを認識させる。
```
# systemctl daemon-reload
```
サーバー起動時にサービスを起動させるよう設定する。
```
# systemctl enable wiki_docker_compose.service
```
設定できたことを確認する。（STATE = enabledであること）
```
# systemctl list-unit-files --type=service | head -1 ; systemctl list-unit-files --type=service | grep wiki
UNIT FILE                                      STATE           VENDOR PRESET
wiki_docker_compose.service                   enabled         enabled
```
サービス起動確認！
```
# systemctl start wiki_docker_compose.service
# systemctl status wiki_docker_compose.service
● wiki_docker_compose.service - wiki docker-compose service
     Loaded: loaded (/etc/systemd/system/wiki_docker_compose.service; enabled; vendor preset: enabled)
     Active: active (exited) since Tue 2025-04-08 07:01:38 JST; 9h ago
   Main PID: 899 (code=exited, status=0/SUCCESS)
        CPU: 243ms

Apr 08 07:01:37 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-app-1  Created
Apr 08 07:01:37 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-reverse-proxy-1  Starting
Apr 08 07:01:37 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-elasticsearch-1  Starting
Apr 08 07:01:37 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-mongo-1  Starting
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-mongo-1  Started
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-reverse-proxy-1  Started
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-elasticsearch-1  Started
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-app-1  Starting
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-app-1  Started
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx systemd[1]: Finished wiki docker-compose service.
```
コンテナ起動確認！
```
CONTAINER ID   IMAGE                 COMMAND                  CREATED       STATUS       PORTS                                           NAMES
05331ed018a3   wiki-app             "dockerize -wait tcp…"   21 seconds ago   Up 19 seconds   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp       wiki-app-1
d521e17e189d   mongo:6.0             "docker-entrypoint.s…"   21 seconds ago   Up 20 seconds   27017/tcp                                       wiki-mongo-1
965971a34b43   wiki-elasticsearch   "/bin/tini -- /usr/l…"   21 seconds ago   Up 20 seconds   9200/tcp, 9300/tcp                              wiki-elasticsearch-1
d9e65c291900   nginx                 "/docker-entrypoint.…"   21 seconds ago   Up 20 seconds   80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   wiki-reverse-proxy-1
```
ジャーナルログ確認！
```
# journalctl -u wiki_docker_compose.service

Apr 08 07:01:35 ip-xxx-xxx-xxx-xxx docker[4392]:  Network wiki_default  Creating
Apr 08 07:01:35 ip-xxx-xxx-xxx-xxx docker[4392]:  Network wiki_default  Created
Apr 08 07:01:35 ip-xxx-xxx-xxx-xxx docker[4392]:  Container wiki-elasticsearch-1  Creating
Apr 08 07:01:36 ip-xxx-xxx-xxx-xxx docker[4392]:  Container wiki-reverse-proxy-1  Creating
Apr 08 07:01:36 ip-xxx-xxx-xxx-xxx docker[4392]:  Container wiki-mongo-1  Creating
Apr 08 07:01:36 ip-xxx-xxx-xxx-xxx docker[4392]:  Container wiki-elasticsearch-1  Created
Apr 08 07:01:36 ip-xxx-xxx-xxx-xxx docker[4392]:  Container wiki-reverse-proxy-1  Created
Apr 08 07:01:36 ip-xxx-xxx-xxx-xxx docker[4392]:  Container wiki-mongo-1  Created
Apr 08 07:01:36 ip-xxx-xxx-xxx-xxx docker[4392]:  Container wiki-app-1  Creating
Apr 08 07:01:37 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-app-1  Created
Apr 08 07:01:37 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-reverse-proxy-1  Starting
Apr 08 07:01:37 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-elasticsearch-1  Starting
Apr 08 07:01:37 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-mongo-1  Starting
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-mongo-1  Started
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-reverse-proxy-1  Started
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-elasticsearch-1  Started
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-app-1  Starting
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx docker[937]:  Container wiki-app-1  Started
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx systemd[1]: Finished wiki docker-compose service.
```
サービス化はこれにて完了です！！！

**～翌日～**

日時のサーバー停止・起動後の状況を見ていきます。

まずはコンテナから。
```
# docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED       STATUS       PORTS                                           NAMES
317ea7647dad   wiki-app             "dockerize -wait tcp…"   2 hours ago   Up 2 hours   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp       wiki-app-1
fc7cf682405f   mongo:6.0             "docker-entrypoint.s…"   2 hours ago   Up 2 hours   27017/tcp                                       wiki-mongo-1
848415d8795e   wiki-elasticsearch   "/bin/tini -- /usr/l…"   2 hours ago   Up 2 hours   9200/tcp, 9300/tcp                              wiki-elasticsearch-1
41e4140baecc   nginx                 "/docker-entrypoint.…"   2 hours ago   Up 2 hours   80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   wiki-reverse-proxy-1
```
無事、サーバー起動後にコンテナが作成されています。

ジャーナルログも見ていきます。
```
# journalctl -u wiki_docker_compose.service

Apr 08 00:05:03 ip-xxx-xxx-xxx-xxx systemd[1]: Stopped wiki docker-compose service.
-- Boot 0f36fb28aeb997ca35855b6a --
～
Apr 08 07:01:38 ip-xxx-xxx-xxx-xxx systemd[1]: Finished wiki docker-compose service.
```
サーバーの停止前にサービスが止まり、起動後にサービスが開始されていることがわかります。

## 4. あとがき
当初、定期的にcompose down/upをさせるための方法として、「AWS側で何かしらのトリガーを利用した仕組みを導入するか？」、「cronで月次のdown/up定義を行うか？」、「cronだと使用中の人がいるタイミングで問題はないか？」などといった複雑な方向で考えていましたが、サービス化でシンプルに解決できました！