systemdでDocker ComposeをLinuxサービスとして実行する
systemd によって管理される起動時の Docker Compose
Linux サーバー上の Docker Compose は、ブート時に起動し、シャットダウン時にクリーンに停止し、手動介入なしで再起動に耐えられるべきです。
Docker Compose は Kubernetes ではありません。このガイドが対象とするワークロードにとって、それで十分です。多くの現実的なシステムにおいて、単一の Linux ホスト上の Compose プロジェクトは、適切なインフラストラクチャの規模です。シンプルで、読みやすく、バックアップが容易で、内部ツール、サイドプロジェクト、セルフホスト型サービス、ステージング環境、小規模な本番アプリ、開発者インフラストラクチャには十分に機能します。

通常欠けている要素は、サービス管理です。以下を手動で実行するだけでは不十分です。
docker compose up -d
この1つのコマンドはスタックを起動しますが、ブート時にスタックがどのように起動し、シャットダウン中に停止し、変更後にリロードし、ログを記録し、障害から回復し、安全に更新されるべきかについて文書化していません。そこで systemd が活躍します。
このガイドでは、Linux サービスとして Docker Compose プロジェクトを systemd と共に実行する方法を解説します。ユニットファイル、ブート順序、更新、ログ、バックアップについて説明します。責任の分離は意図的なものです。Docker はコンテナを実行し、Compose はスタックを定義し、systemd はホスト上のプロジェクトの起動と停止を行います。これは 開発ツール - 開発ワークフローガイド の一部です。
Docker Compose をサービスとして運用する場合
systemd 下で Compose を実行するのは、以下のような場合に意味があります。
- 単一の Linux サーバー
- 小規模なセルフホスト型アプリケーション
- リバースプロキシスタック
- モニタリングスタック
- ローカル開発プラットフォーム
- 内部ツール
- ステージング環境
- 制限が明確な単純な本番サービス
例:
- Nginx Proxy Manager
- Traefik
- Gitea
- Grafana と Prometheus
- PostgreSQL と小規模なウェブアプリ
- Uptime Kuma
- Home Assistant のヘルパーサービス
- プライベートレジストリ
- 内部 API、ワーカー、Redis
Compose は、1人が1つのディレクトリを読むことで運用モデルを理解できる場合に適しています。
Docker Compose では不十分な場合
以下が必要な場合は、他のソリューションを使用してください。
- マルチノードスケジューリング
- ホスト間での自動スケジューリング
- クラスターレベルのサービスディスカバリ
- 水平オートスケーリング
- 多数のマシンへのローリングデプロイ
- 細粒度のワークロードアイデンティティ
- 複雑なネットワークポリシー
- 大規模なマルチチームプラットフォーム運用
その段階では、Kubernetes、Nomad、Swarm、またはマネージドプラットフォームの方が適しているかもしれません。
私の実践的なルールは、systemd を学ぶことを避けるために Kubernetes を使うのを避け、また複数のホスト間でのオーケストレーションが明らかに必要なワークロードで Compose を使うのを避けることです。
基本的なアーキテクチャ
クリーンなセットアップでは、プロジェクトファイル、systemd ユニット、ホスト上の永続データを分離します。Compose プロジェクトは /opt/myapp/ の下に存在し、compose.yaml、.env、data/、backups/、および scripts/update.sh などのオプションのスクリプトを含みます。systemd ユニットファイルは /etc/systemd/system/myapp.service に配置されます。
各レイヤーには明確な役割があります。Docker はコンテナを実行し、Compose はアプリケーションスタックを定義し、systemd はブートおよびシャットダウン時に Compose プロジェクトの起動と停止を行います。ホストファイルシステムは永続データを保存し、バックアップは明示的に保持され、更新はスクリプト化されたレビュー可能なステップを通じて行われます。このレイアウトは意図的に退屈なものです。なぜなら、退屈なインフラストラクチャは、午前2時に何か壊れたときに修理しやすいからです。
Compose プロジェクトディレクトリの準備
/opt の下にディレクトリを作成します。
sudo mkdir -p /opt/myapp
sudo chown -R "$USER":"$USER" /opt/myapp
cd /opt/myapp
Compose ファイルを作成します。
nano compose.yaml
例:
services:
web:
image: nginx:stable
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
healthcheck:
test: ["CMD-SHELL", "nginx -t || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes: {}
コンテンツディレクトリを作成します。
mkdir -p html
echo "Hello from Docker Compose" > html/index.html
まず手動でテストします。
docker compose up -d
docker compose ps
docker compose logs --tail=50
次に、ライフサイクルを systemd に引き継ぐ前に停止します。
docker compose down
Compose プロジェクトが手動で動作するまで、systemd サービスを作成しないでください。テスト中は ps、logs、pull、およびプロジェクト構造のために Docker Compose チートシート を近くに置いておいてください。
最新の docker compose コマンドを使用する
ユニットファイルを書く前に、Docker Engine と Compose プラグインがインストールされている必要があります。Ubuntu では、Ubuntu に Docker をインストールする で APT、Snap、ルートレスモード、およびインストール後のセキュリティについて説明しており、機能する docker compose コマンドが得られるようになります。
これを使用します。
docker compose version
これではありません。
docker-compose version
古い docker-compose バイナリはまだ多くのマシンに存在しますが、最新の Docker は Compose を Docker CLI プラグインとして使用します。
サービスファイルおよびスクリプトでは、以下を優先します。
/usr/bin/docker compose
Docker パスは以下で見つけることができます。
command -v docker
通常は以下の通りです。
/usr/bin/docker
Docker Compose 用の systemd サービスを作成する
ユニットファイルがわからない場合は、Linux で任意の実行ファイルをサービスとして実行する で Type、ExecStart、systemctl、および一般的な systemd ワークフローについて説明しています。このセクションでは、これらのパターンを Compose スタックに特化して適用します。
サービスファイルを作成します。
sudo nano /etc/systemd/system/myapp.service
このユニットを使用します。
[Unit]
Description=MyApp Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
systemd をリロードします。
sudo systemctl daemon-reload
サービスを開始します。
sudo systemctl start myapp.service
ブート時に有効にします。
sudo systemctl enable myapp.service
ステータスを確認します。
systemctl status myapp.service
コンテナを確認します。
cd /opt/myapp
docker compose ps
なぜ Type=oneshot と RemainAfterExit=yes なのか?
多くのガイドで微妙に誤解されがちなのはここです。
docker compose up -d はデタッチモードでコンテナを起動し、終了します。そのため、systemd が監督する長時間実行されるフォアグラウンドの Compose プロセスはありません。systemd ユニットは docker compose up -d が長時間実行されるデーモンであると偽ってはいけません。
これを使用します。
Type=oneshot
RemainAfterExit=yes
これは systemd に以下を指示します。
- スタートコマンドを実行する。
- コマンドが正常に終了した後、ユニットをアクティブとみなす。
- サービスが停止されたときに
ExecStopを実行する。
これはデタッチされた Compose の実際の動作と一致するため、Type=oneshot と RemainAfterExit=yes はほとんどのスタックにとって正しいデフォルトです。
なぜ Type=simple ではないのか?
Type=simple では、systemd は ExecStart プロセスが実行され続けることを期待しますが、docker compose up -d はコンテナを起動した後終了します。これにより、systemd はサービスが終了したと誤認し、設定に応じて停止ロジックを呼び出したり、ユニットを非アクティブとマークしたりする可能性があります。
Type=simple を使用したい場合は、通常 Compose をフォアグラウンドで実行します。
ExecStart=/usr/bin/docker compose up
これは機能しますが、サーバー上の Compose スタックには通常好んで使用しません。デタッチされたコンテナと明示的な ExecStop の方が運用が容易です。
より本番環境向けのユニット
実際のサーバーでは、少し厳格なユニットを好みます。
[Unit]
Description=MyApp Docker Compose stack
Documentation=https://example.com/docs/myapp
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
EnvironmentFile=-/opt/myapp/.env.systemd
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
重要な詳細:
WorkingDirectoryは Compose プロジェクトを指します。ExecStartPreは Compose 設定を検証します。ExecReloadは変更されたサービスを再作成します。ExecStopは Compose プロジェクトのコンテナとデフォルトネットワークを停止して削除します。EnvironmentFile=-...はファイルがオプションであることを意味します。
オプションの systemd 環境ファイルを作成します。
nano /opt/myapp/.env.systemd
例:
COMPOSE_PROJECT_NAME=myapp
次に systemd をリロードします。
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
Compose .env と systemd EnvironmentFile
Compose と systemd はそれぞれ独自の環境メカニズムを持っており、これらを混同するとブート時に「変数が設定されていません」という混乱するエラーが発生します。
Compose は、Compose ファイルの変数置換のためにプロジェクトディレクトリ内の .env ファイルを自動的に読み込みます。
例 .env:
APP_TAG=1.2.3
WEB_PORT=8080
例 compose.yaml:
services:
web:
image: nginx:${APP_TAG}
ports:
- "${WEB_PORT}:80"
systemd の EnvironmentFile は docker compose コマンド自体の環境変数を設定します。
例:
EnvironmentFile=-/opt/myapp/.env.systemd
多くのプロジェクトでは、Compose .env だけで十分です。
以下のようなものを定義したい場合に systemd 環境ファイルを使用します。
COMPOSE_PROJECT_NAME=myapp
COMPOSE_FILE=compose.yaml
DOCKER_HOST=unix:///var/run/docker.sock
どちらのファイルもカジュアルなシークレット保管庫として使用しないでください。シークレットが重要な場合は、Docker シークレット、外部シークレットマネージャー、暗号化されたファイル、または少なくとも厳格な権限を使用してください。
制限的な権限を設定します。
chmod 600 /opt/myapp/.env
chmod 600 /opt/myapp/.env.systemd
再起動ポリシー: Docker と systemd
再起動ポリシーには2つのレイヤーがあります。Compose 内のコンテナ再起動ポリシーと systemd サービス再起動ポリシーであり、これらを盲目的に混用しないでください。
長時間実行されるコンテナの場合、Compose で再起動ポリシーを設定します。
services:
web:
image: nginx:stable
restart: unless-stopped
一般的な再起動値:
| ポリシー | 意味 |
|---|---|
| no | 自動的に再起動しない |
| always | 終了後およびデーモン再起動後に再起動 |
| on-failure | 失敗後にのみ再起動 |
| unless-stopped | 手動で停止されない限り再起動 |
ほとんどの永続サービスでは、以下を好みます。
restart: unless-stopped
予測可能で、意図的な手動停止を尊重します。
systemd ユニット自体は通常繰り返し再起動すべきではありません。なぜなら docker compose up -d は実行中のワークロードではないからです。コンテナがそうなのです。
したがって、特定の理由がない限り、以下を避けてください。
Restart=always
ほとんどの Compose-as-service ユニットでは、コンテナの再起動を Docker に任せてください。
ヘルスチェック
再起動ポリシーはプロセスが終了したときにコンテナを再起動します。しかし、すべての不健康なアプリケーションを魔法のように修正するわけではありません。
役立つ場所にヘルスチェックを追加します。
services:
app:
image: example/app:latest
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:8080/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
ヘルスを確認します。
docker compose ps
コンテナを検査します。
docker inspect container-name
ヘルスチェックは以下に特に有用です。
- ウェブアプリ
- リバースプロキシ
- データベース
- キュー
- 内部 API
- ヘルスエンドポイントを持つワーカー
プロセスが存在することのみをチェックする場合、それらはあまり有用ではありません。なぜなら、生きていますが固まっているプロセスは依然として健全に見えるからです。悪いヘルスチェックは単に YAML における別の嘘です。
スタートアップ順序と depends_on
Compose は依存関係を定義できます。
services:
app:
image: example/app:latest
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
これはスタートアップ順序の助けになりますが、過度に信頼しないでください。アプリケーションは依然としてリトライを処理する必要があります。データベースは再起動し、ネットワークは不安定になり、DNS には時間がかかります。強靭なアプリは、完璧なスタートアップ順序を仮定するのではなく、接続をリトライします。
ログ: journalctl と docker compose logs
2つのログビューがほとんどのデバッグをカバーします。systemd はユニット自体のライフサイクルをキャプチャし、Compose は実行中のコンテナからのアプリケーション出力をキャプチャします。
systemd サービスログ:
journalctl -u myapp.service -n 100 --no-pager
systemd ログを追従します。
journalctl -u myapp.service -f
Compose サービスログ:
cd /opt/myapp
docker compose logs --tail=100
docker compose logs -f
docker compose logs -f web
ほとんどのアプリデバッグでは docker compose logs の方が有用ですが、ライフサイクルデバッグ — 起動障害、ユニットクラッシュ、権限エラー — では journalctl の方が有用です。systemctl start myapp が失敗した場合は、まず journalctl をチェックしてください。スタックが起動したがアプリが破損している場合は、docker compose logs をチェックしてください。
ログローテーション
設定しないと、Docker ログは永遠に増大します。
小規模なサーバーの場合、/etc/docker/daemon.json で Docker ログローテーションを設定します。
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}
Docker を再起動します。
sudo systemctl restart docker
次に Compose スタックを再起動します。
sudo systemctl restart myapp.service
これは新しく作成されたコンテナに適用されます。必要に応じてコンテナを再作成します。
cd /opt/myapp
docker compose up -d --force-recreate
ログローテーションは派手ではありませんが、小規模なサーバーでのディスクフル障害を防ぐ最も簡単な方法の1つです。
Compose サービスの更新
単純な手動更新フロー:
cd /opt/myapp
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
systemd によって管理されている場合は、以下を使用できます。
sudo systemctl reload myapp.service
ユニットに以下がある場合:
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ただし、ExecReload はそのステップを含めない限りイメージをプルしないことに注意してください。
明示的な更新のために、スクリプトを作成します。
mkdir -p /opt/myapp/scripts
nano /opt/myapp/scripts/update.sh
スクリプト:
#!/usr/bin/env bash
set -euo pipefail
cd /opt/myapp
docker compose config --quiet
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
docker compose ps
実行可能にします。
chmod +x /opt/myapp/scripts/update.sh
実行します。
/opt/myapp/scripts/update.sh
その後、サービスユニットはライフサイクルに集中し、更新スクリプトがデプロイを処理します。
バックアップフック付きのより安全な更新スクリプト
ステートフルなサービスの場合、バックアップ後にのみ更新します。
#!/usr/bin/env bash
set -euo pipefail
APP_DIR="/opt/myapp"
BACKUP_DIR="/opt/myapp/backups"
cd "$APP_DIR"
mkdir -p "$BACKUP_DIR"
echo "Validating compose file"
docker compose config --quiet
echo "Running backup hook"
if [ -x "$APP_DIR/scripts/backup.sh" ]; then
"$APP_DIR/scripts/backup.sh"
else
echo "No backup hook found"
fi
echo "Pulling images"
docker compose pull
echo "Recreating services"
docker compose up -d --remove-orphans
echo "Pruning unused images"
docker image prune -f
echo "Current status"
docker compose ps
これは依然としてシンプルですが、今や運用習慣をエンコードしています:変更前にバックアップ。
サービスの停止
スタックを停止します。
sudo systemctl stop myapp.service
これにより以下が実行されます。
docker compose down
デフォルトでは、docker compose down は以下を削除します。
- Compose ファイル内のサービスのコンテナ
- Compose ファイルで定義されたネットワーク
- デフォルトネットワーク
名前付きボリュームを要求しない限り、削除しません。
以下をカジュアルに使用しないでください。
docker compose down -v
これにより、Compose ファイルで宣言された名前付きボリュームとコンテナに接続された匿名ボリュームが削除されます。データベースやステートフルなアプリの場合、これは実際のデータの削除を意味する可能性があります。
down -v は「この環境を破壊する」と意図する場合にのみ使用してください。
サービスの再起動
systemd ユニットを再起動します。
sudo systemctl restart myapp.service
これにより停止コマンドが実行され、その後開始コマンドが実行されます。
コンテナを再作成せずに再起動するのみ:
cd /opt/myapp
docker compose restart
重要な違い:
docker compose restartは既存のコンテナを再起動します。docker compose up -dは必要に応じてコンテナを再作成して設定またはイメージの変更を適用します。
compose.yaml を変更した場合は、以下を使用します。
docker compose up -d
以下のみではありません。
docker compose restart
孤立コンテナの処理
compose.yaml でサービスの名前を変更または削除した場合、古いコンテナが孤立として残る可能性があります。
これを使用します。
docker compose up -d --remove-orphans
このガイドの systemd サービスの例が以下を使用する理由です。
ExecStart=/usr/bin/docker compose up -d --remove-orphans
これにより、スタックは現在の Compose ファイルに近づきます。
バックアップ
バックアップはワークロードに依存しますが、原則は安定しています。
バインドマウントの場合:
/opt/myapp/data/
そのディレクトリをバックアップします。
名前付きボリュームの場合:
docker volume ls
ボリュームを検査します。
docker volume inspect volume-name
データベースの場合、ファイルシステムのコピーだけでは十分ではありません。アプリケーション対応のバックアップを使用します。
PostgreSQL の例:
docker compose exec -T db pg_dump -U postgres appdb > backups/appdb.sql
MariaDB の例:
docker compose exec -T db mariadb-dump -u root -p appdb > backups/appdb.sql
Redis の例:
docker compose exec redis redis-cli BGSAVE
バックアッププランのない Compose スタックはサービスではありません。アップタイムがある一時的な実験に過ぎません。
セキュリティベースライン
Linux 上の小規模な Compose サービスの場合、このベースラインから始めます。
- Compose プロジェクトを
/opt/appnameの下に保つ。 - 安定性が重要な場合は、
latestだけでなく明示的なイメージタグを使用する。 - バインドマウントまたは名前付きボリュームを意図的に使用する。
- 必要ないポートを公開しない。
- パブリックサービスをリバースプロキシの背後に置く。
- エッジで HTTPS を使用する。
- Git からシークレットを外す。
.envの権限を制限する。- 真に必要でない限り、特権コンテナを避ける。
- コンテナに Docker ソケットをマウントしない。
- Docker とイメージを更新する。
- 別のマシンからファイアウォールの動作をテストする。
危険なパターン:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
これにより、コンテナが Docker の制御を得ます。実際には、ホストレベルの制御になる可能性があります。リスクを理解している場合にのみ使用してください。
リソース制限
小規模なサーバーでは、1つの悪いコンテナがホストを消費する可能性があります。
Compose はリソース関連の設定をサポートしていますが、動作は Docker Engine と Compose のバージョンに依存する場合があります。単純な保護のために、アプリケーションレベルの制限と Docker ログ制限から始めます。
一部のワークロードでは、メモリ制限を追加できます。
services:
app:
image: example/app:stable
restart: unless-stopped
mem_limit: 512m
また、アプリケーションレベルのワーカー数、キュー制限、キャッシュサイズも設定します。コンテナ制限は有用ですが、アプリケーションを理解する替代品ではありません。
例: 現実的な Compose サービス
ディレクトリ:
/opt/whoami/
compose.yaml
.env
Compose ファイル:
services:
whoami:
image: traefik/whoami:v1.10
restart: unless-stopped
ports:
- "${WHOAMI_PORT}:80"
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost || exit 1"]
interval: 30s
timeout: 5s
retries: 3
.env ファイル:
WHOAMI_PORT=8080
COMPOSE_PROJECT_NAME=whoami
systemd ユニット:
[Unit]
Description=Whoami Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/whoami
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
インストールします。
sudo systemctl daemon-reload
sudo systemctl enable --now whoami.service
テスト:
curl http://localhost:8080
ステータスを確認します。
systemctl status whoami.service
cd /opt/whoami
docker compose ps
トラブルシューティング
サービスが起動するがコンテナが実行されていない
systemd を確認します。
journalctl -u myapp.service -n 100 --no-pager
Compose を検証します。
cd /opt/myapp
docker compose config
Docker を確認します。
systemctl status docker
docker info
WorkingDirectory が間違っている
systemd が Compose ファイルを見つけられない場合は、以下を確認します。
WorkingDirectory=/opt/myapp
次に確認します。
ls -la /opt/myapp
ls -la /opt/myapp/compose.yaml
サービスは現在のシェルディレクトリではなく WorkingDirectory から実行されます。
Docker 権限拒否
ユニットがルートとして実行される場合、通常 Docker にアクセスできます。
User=someuser を設定した場合、そのユーザーは Docker にアクセスできる必要があります。通常、これは docker グループのメンバーシップ、またはルートレス Docker セットアップを意味します。
確認します。
groups someuser
適切であればユーザーを追加します。
sudo usermod -aG docker someuser
注意が必要です。Docker グループは実質的に特権的です。
Compose コマンドが見つからない
Docker を探します。
command -v docker
ユニットでフルパスを使用します。
ExecStart=/usr/bin/docker compose up -d --remove-orphans
Compose プラグインが欠落している場合:
docker compose version
Docker パッケージソースを使用してインストールします。
環境変数が不足している
systemd がどのように見えるか Compose 設定を確認します。
cd /opt/myapp
docker compose config
systemd に追加の環境変数が必要な場合は、以下を使用します。
EnvironmentFile=-/opt/myapp/.env.systemd
Compose に置換用の変数が必要な場合は、以下を使用します。
/opt/myapp/.env
これらは関連していますが、同一ではありません。
再起動後にコンテナが起動しない
systemd サービスが有効になっているか確認します。
systemctl is-enabled myapp.service
有効にします。
sudo systemctl enable myapp.service
Docker を確認します。
systemctl is-enabled docker
systemctl status docker
ブートログを確認します。
journalctl -u myapp.service -b --no-pager
アプリがデータベース準備完了前に起動する
データベースヘルスチェックと service_healthy 付きの depends_on を追加します。
また、アプリケーションも修正します。データベース接続をリトライするべきです。インフラストラクチャのスタートアップ順序は役立ちますが、アプリケーションのリトライロジックの方が優れています。
Docker ログでディスクが埋め尽くされる
Docker のディスク使用量を確認します。
docker system df
大きなコンテナログを確認します。
sudo du -h /var/lib/docker/containers | sort -h | tail
/etc/docker/daemon.json で Docker ログローテーションを設定します。
次にコンテナを再作成します。
一般的な間違い
間違い 1: rc.local で docker compose up を実行する
rc.local またはログインスクリプトから docker compose up を実行するのは、機能しなくなるまで機能します。代わりに適切な systemd ユニットを使用してください。
間違い 2: systemd で Restart=always と Compose で restart: always を使用する
通常、Compose でコンテナ再起動ポリシーのみが必要です。2つのスーパーバイザーが互いに戦うのを避けてください。
間違い 3: –remove-orphans を忘れる
サービスの名前変更と削除により、古いコンテナが残る可能性があります。以下を使用します。
docker compose up -d --remove-orphans
間違い 4: 設定変更後に docker compose restart を使用する
restart はコンテナを再起動します。すべての設定変更を適用しません。
以下を使用します。
docker compose up -d
間違い 5: 考えずに down -v を実行する
これによりボリュームが削除される可能性があります。ステートフルなサービスの場合、これはデータの削除を意味する可能性があります。
間違い 6: Pull 前にバックアップなし
新しいイメージは壊れる可能性があります。データベースはマイグレーションする可能性があります。タグは移動する可能性があります。まずバックアップしてください。
間違い 7: すべてのポートを公開する
ホストが公開する必要があるもののみを公開してください。内部サービス間のトラフィックは Compose ネットワーク上にとどまることができます。
最終的な推奨パターン
ほとんどの単一ホスト Linux サービスの場合、このパターンを使用します。
Compose ファイル:
services:
app:
image: example/app:stable
restart: unless-stopped
ports:
- "8080:8080"
env_file:
- .env
systemd ユニット:
[Unit]
Description=MyApp Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
有効にします。
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
運用します。
sudo systemctl status myapp.service
sudo systemctl restart myapp.service
journalctl -u myapp.service -f
cd /opt/myapp && docker compose logs -f
このパターンは派手ではありません。それがポイントです。Docker Compose は小規模で理解しやすいシステムに優れ、systemd はホストサービスの起動と停止に優れており、共にすべてのプロジェクトにクラスターが必要であると偽ることなく、信頼性の高い単一サーバーデプロイモデルを提供します。Compose 外でのコンテナレベルのコマンド — イメージ、ボリューム、ネットワーク、およびクリーンアップ — については、Docker チートシート を参照してください。