有馬総一郎のブログ

(彼氏の事情)

2025年08月24日 06:30:51 JST - 4 minute read - Linux

Ubuntu Server起動時に`Rooteless`モードでDocker Composeを自動実行する(systemd編)

Ubuntu Serverを起動した際に、特定のdocker composeコマンドを自動で実行したい。ホームディレクトリにある docker-compose.yaml のDockerサービスは自動で起動できている。

ぱっと思いついたのが、systemdサービスを作成すること。この記事では、ユーザーサービスとしてsystemdサービスを登録し、RootlessモードでDocker Composeを自動起動する手順をまとめておく。

背景

やりたいことはシンプルで、 Seafileを起動するためのdocker compose --env-file seafile/.env -f seafile/seafile_compose.yaml startコマンドをサーバー起動時に自動実行する。

すでに、ユーザーサービスの定義ファイルを置くためのディレクトリを作成されていた。

$ ls -l ~/.config/systemd/user/
合計 12
drwxr-xr-x 2 arimasou16 arimasou16 4096  8月 22 09:05 default.target.wants
-rw-rw-r-- 1 arimasou16 arimasou16  603  2月 10  2024 docker.service
-rw-rw-r-- 1 arimasou16 arimasou16  463  8月 22 09:03 seafile.service

ちなみにdocker.serviceの中身はこうなっている。

~/.config/systemd/user/docker.service

[Unit]
Description=Docker Application Container Engine (Rootless)
Documentation=https://docs.docker.com/go/rootless/

[Service]
Environment=PATH=/usr/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/nvim-linux64/bin
ExecStart=/usr/bin/dockerd-rootless.sh
・・・以下、後略・・・

次に、ユーザーサービスの定義ディレクトリ内にseafile.serviceという名前でサービスファイルを作成する。

~/.config/systemd/user/seafile.service

[Unit]
Description=Seafile Docker Compose User Service
After=docker.service
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
Environment="DOCKER_HOST=unix:///run/user/1000/docker.sock"
WorkingDirectory=/home/arimasou16
ExecStart=/usr/bin/docker compose --env-file seafile/.env -f seafile/seafile_compose.yaml start
ExecStop=/usr/bin/docker compose --env-file seafile/.env -f seafile/seafile_compose.yaml stop

[Install]
WantedBy=default.target
  • [Unit]セクション: docker.serviceの起動後にこのサービスが起動するように依存関係を設定する。
  • [Service]セクション:
    • Type=oneshot: 単発のタスクとして実行する。
    • RemainAfterExit=yes: ExecStartのプロセスが終了してもサービスを有効状態に保ち、ExecStopが実行できるようにする。
    • WorkingDirectory: コマンドを実行するディレクトリを絶対パスで指定する。
  • [Install]セクション: WantedBy=default.targetは、ユーザーがログインしたときにサービスが自動的に起動するようにするための標準的な設定をする。

2. サービスを有効化して起動

ファイルを作成したら、設定をリロードしてサービスを有効化する。ユーザーサービスなので--userフラグを付け、sudoは不要。

# 設定を再読み込み
systemctl --user daemon-reload

# ユーザーログイン時の自動起動を有効化
systemctl --user enable seafile.service

# サービスを手動で起動してみる
systemctl --user start seafile.service

3. トラブルシューティング

上記の手順で進めたところ、いくつかのエラーに遭遇した。

エラー1: Unit network-online.target not found.

当初、ネットワークが有効になってからサービスを起動しようとAfter=network-online.targetを追加していたが、このエラーが発生した。

これは、network-online.targetがユーザーセッションでは必ずしも有効ではないために起こった。

解決策: docker.service自体がネットワークの準備ができてから起動するため、seafile.servicedocker.serviceの後に起動するように設定されば、間接的にネットワークの問題は解決される。そのため、サービスファイルからnetwork-online.targetの記述を削除した(上記の設定ファイルは修正済みのもの)。

エラー2: DockerソケットへのPermission denied

permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock

これは、DockerをRootlessモードで運用していることが原因だった。

RootlessモードのDockerソケットは、システム用の/var/run/docker.sockではなく、ユーザーディレクトリ内の/run/user/1000/docker.sock(1000はユーザーID)にある。systemdのユーザーサービスが、デフォルトのシステム用ソケットに接続しようとしてエラーになっていた。

解決策: サービスファイルに環境変数DOCKER_HOSTを追加し、正しいソケットのパスを明示的に指定する。

最終的なseafile.serviceファイルは上記のようになった。

この修正後に再度systemctl --user daemon-reloadsystemctl --user start seafile.serviceを実行すると、無事にサービスが起動できた。

まとめ

以上の設定で、ユーザーログイン時に自動でDocker Composeのコンテナが起動するようになった。