こう尋ねるエンジニアをセミナーでもよく見かける。手元のPCではdocker compose upで問題なく動作していても、docker stack deployに切り替えた瞬間に「buildキーは無視される」「depends_onが機能しない」という壁にぶつかる。
この記事では、compose.ymlをDocker Swarmへ持ち込む際の互換性を体系的に整理し、docker stack deployで有効なdeployキーと無視されるキーの違い・対処法をコマンド実例付きで解説します。Rocky Linux 9.4 / Ubuntu 24.04 LTSで動作確認済みです。
この記事のポイント
・docker stack deployはdeployブロック(replicas・placement・restart_policy)を読み取りSwarmサービスを構成する
・build・depends_on・restartキーはdocker stack deployでは完全に無視される
・buildを使っているサービスは「ビルド→レジストリpush→image:書き換え」の3ステップで対応する
・depends_onの代替はhealthcheck + deploy.restart_policy.condition: on-failureで吸収できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
Docker SwarmとDocker Compose、何が根本的に違うのか
docker compose upとdocker stack deployは、どちらもcompose.yml(またはdocker-compose.yml)を読む点では同じに見える。しかし内部の動作モデルは大きく異なる。docker compose upはシングルホスト上でコンテナを起動するツールだ。compose.ymlに書かれたほぼすべてのキー(build、depends_on、restart、container_name、links等)を処理する。
一方、docker stack deployはDocker Swarmクラスターに対してサービスを宣言的にデプロイするコマンドだ。複数ノードにまたがるため、「1台のPCでしか意味をなさないキー」は設計上サポートされない。具体的には以下の違いがある。
| 項目 | docker compose up | docker stack deploy |
|---|---|---|
| 実行環境 | シングルホスト | Swarmクラスター(マルチノード可) |
| build:キー | 有効(その場でビルド) | 無視される(事前にpush必須) |
| depends_on:キー | 有効(起動順序を制御) | 無視される(同時起動) |
| deploy:キー | 基本的に無視 | 有効(replicas・placementなど) |
| restart:キー | 有効 | 無視(deploy.restart_policyを使う) |
| container_name:キー | 有効 | 無視(Swarmが管理) |
compose.ymlをSwarm対応に調整してdocker stack deployで展開する基本手順
実際にcompose.ymlをSwarmに持ち込む手順を順を追って説明する。1. Docker Swarmを初期化する
まだSwarmを起動していない場合は、マネージャーノードで以下を実行する。$ docker swarm init --advertise-addr 192.168.1.10 Swarm initialized: current node (abc123xyz) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-xxx 192.168.1.10:2377
2. compose.ymlをSwarm対応に調整する
既存のcompose.ymlがある場合、Swarmで無視されるキーを取り除き、deployブロックを追加する。以下はWordPressとMySQLの構成例だ。修正前(docker compose up向け):
services: db: image: mysql:8.0 restart: always # ← Swarmでは無視される container_name: wp_db # ← Swarmでは無視される environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: wordpress wordpress: build: . # ← Swarmでは無視される(事前にpush必須) depends_on: - db # ← Swarmでは無視される ports: - "80:80" environment: WORDPRESS_DB_HOST: db:3306
services: db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: wordpress deploy: replicas: 1 restart_policy: condition: on-failure max_attempts: 3 placement: constraints: - node.role == manager wordpress: image: myrepo/wordpress:latest # ← buildの代わりにpush済みイメージを指定 ports: - "80:80" environment: WORDPRESS_DB_HOST: db:3306 deploy: replicas: 2 restart_policy: condition: on-failure update_config: parallelism: 1 delay: 10s networks: default: driver: overlay
3. docker stack deployを実行する
# スタック名を "myapp" として展開する $ docker stack deploy -c compose.yml myapp Creating network myapp_default Creating service myapp_db Creating service myapp_wordpress
4. デプロイ状態を確認する
# サービス一覧を確認する $ docker service ls ID NAME MODE REPLICAS IMAGE a1b2c3d4e5f6 myapp_db replicated 1/1 mysql:8.0 f6e5d4c3b2a1 myapp_wordpress replicated 2/2 myrepo/wordpress:latest # 特定サービスのタスク(コンテナ)状態を確認する $ docker service ps myapp_wordpress ID NAME IMAGE NODE DESIRED STATE CURRENT STATE x1y2z3a4b5c6 myapp_wordpress.1 myrepo/wordpress:latest node01 Running Running 2 minutes ago c6b5a4z3y2x1 myapp_wordpress.2 myrepo/wordpress:latest node02 Running Running 2 minutes ago
docker stack deployで有効なdeployキー一覧
deployブロック配下のキーは、docker stack deployで初めて意味を持つ。主要なキーを実例付きで整理する。replicas(レプリカ数)
deploy: replicas: 3 # サービスを3コンテナで動かす
どのノードにコンテナを配置するかを制御する。node.role、node.labels、node.hostnameなどが使える。
deploy: placement: constraints: - node.role == worker # ワーカーノードにのみ配置 - node.labels.region == tokyo # ラベルで絞り込む場合
$ docker node update --label-add region=tokyo node01
deploy: update_config: parallelism: 1 # 同時に更新するコンテナ数 delay: 10s # 各バッチ間の待機時間 failure_action: rollback # 失敗したら自動ロールバック order: start-first # 新コンテナを先に起動してから旧コンテナを停止
deploy: restart_policy: condition: on-failure # 失敗時のみ再起動(any / none も指定可能) delay: 5s # 再起動前の待機時間 max_attempts: 3 # 最大再起動回数(超えたらタスクを停止) window: 120s # max_attemptsをカウントする時間窓
deploy: resources: limits: cpus: '0.50' # CPUの上限(コア数の割合) memory: 512M # メモリの上限 reservations: cpus: '0.25' # スケジューリング時に確保するCPU memory: 256M # スケジューリング時に確保するメモリ
deploy: mode: global # 全ノードに1コンテナずつ配置(監視エージェントなどに使う) # mode: replicated # デフォルト。replicasで数を指定
docker stack deployで無視されるキー(要注意)
以下のキーはdocker compose upでは有効だが、docker stack deployでは完全に無視される。エラーにはならないため、うっかり残したまま展開しても気づきにくい点に注意が必要だ。・build:Swarmはイメージをビルドしない。image:でレジストリ上のイメージを指定する必要がある
・depends_on:Swarmはサービスの起動順序を制御しない。すべてのサービスがほぼ同時に起動される
・restart:deploy.restart_policyで代替する(restart: alwaysとは設定方法が異なる)
・container_name:Swarmはコンテナ名を「スタック名_サービス名.タスク番号」形式で自動管理する
・links:レガシー機能のため非サポート。overlayネットワーク上ではサービス名でDNS解決できる
・network_mode: host:Swarmのopenポートでは使えない。ホストネットワークが必要な場合は別途検討が必要
buildキーを使っている場合の対処法
compose.ymlにbuild:が含まれているサービスをSwarmで動かすには、「ビルド→レジストリへpush→image:に書き換え」の3ステップが必要だ。1. イメージをビルドしてタグを付ける
# カレントディレクトリのDockerfileを使ってビルドする $ docker build -t myrepo/myapp:v1.0 . # Docker Hubに送る場合は事前にログインしておく $ docker login
2. レジストリにpushする
$ docker push myrepo/myapp:v1.0 The push refers to repository [docker.io/myrepo/myapp] v1.0: digest: sha256:abc123... size: 1234
3. compose.ymlのbuild:をimage:に書き換える
# 修正前 services: app: build: . ports: - "8080:8080" # 修正後 services: app: image: myrepo/myapp:v1.0 # pushしたイメージを指定 ports: - "8080:8080" deploy: replicas: 2
トラブルシュート|よくあるエラーと対処
サービスが「Preparing」から進まない
docker service psを実行してCURRENT STATE列を確認する。「Preparing」が続く場合はイメージのpullに失敗している可能性が高い。$ docker service ps myapp_wordpress --no-trunc ID NAME IMAGE NODE DESIRED CURRENT STATE ERROR xxx myapp_wordpress.1 myrepo/wordpress:latest node02 Running Preparing 3 min "No such image: myrepo/wordpress:latest"
「no suitable node」エラーが出る
placementのconstraintsが厳しすぎて、条件に合うノードが存在しない場合に発生する。# ノードの状態とラベルを確認する $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS abc123 * node01 Ready Active Leader def456 node02 Ready Active # ノードに付いているラベルを確認する $ docker node inspect node02 --pretty | grep -A 5 Labels Labels: - region=osaka
depends_onが効かずDB接続エラーが出る
Swarmではdepends_onが無視されるため、DBが完全に起動する前にアプリが接続を試みてエラーになることがある。対処法は2つある。・アプリ側で接続リトライロジックを実装する(最も根本的な解決策)
・deploy.restart_policy.condition: on-failureを設定し、DB起動完了後にアプリが自動再起動するのを待つ
deploy: restart_policy: condition: on-failure max_attempts: 5 # 最大5回リトライする間にDBが起動するのを待つ delay: 5s
スタックの更新(再デプロイ)方法
設定変更後は同じコマンドを再実行するだけでよい。Swarmはdiff差分を適用し、変更のあったサービスのみをローリングアップデートする。# 同じコマンドで再実行すると差分が適用される $ docker stack deploy -c compose.yml myapp Updating service myapp_wordpress (id: f6e5d4c3b2a1) # スタックを完全に削除する場合 $ docker stack rm myapp
本記事のまとめ
docker stack deployとcompose.ymlの互換性の早見表です。| キー | docker stack deployでの扱い | 代替手段 |
|---|---|---|
| deploy.replicas | 有効 | — |
| deploy.placement | 有効 | — |
| deploy.update_config | 有効 | — |
| deploy.restart_policy | 有効 | — |
| deploy.resources | 有効 | — |
| build | 無視される | ビルド後にimage:でpush済みイメージを指定 |
| depends_on | 無視される | アプリ側リトライ + restart_policy.condition: on-failure |
| restart | 無視される | deploy.restart_policyに移行 |
| container_name | 無視される | Swarmが「スタック名_サービス名.N」形式で自動付与 |
・compose.ymlをSwarmに持ち込む際は、buildをimage:に、restartをdeploy.restart_policyに置き換えるのが最初の作業になる
・deployブロック(replicas・placement・update_config・restart_policy・resources)はdocker stack deployで初めて有効になる
・depends_onの代替はアプリ側リトライとrestart_policy.on-failureの組み合わせで対応する
・サービスが「Preparing」から進まない場合はdocker service ps --no-truncでイメージpullのエラーを確認する
Docker実践講座の詳細を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Docker Composeのビルド設計|buildセクションのcontext・args・キャッシュでイメージ更新を制御する
- この記事の属するカテゴリ:Dockerへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます