こんにちは!インフラエンジニアの先輩です。
新しい技術を触るとき、「思った通りに動かない」「エラーの意味が分からない」と手が止まってしまうことって、エンジニアなら誰もが通る道ですよね。特に複数のサーバーを束ねてコンテナを動かすオーケストレーションの世界へ足を踏み入れると、最初は魔法のように見えて、ひとたび壊れると黒魔術のように感じられるものです。
今回は、軽量でシンプルなコンテナオーケストレーションツール「Docker Swarm」を取り上げます。
K8s(Kubernetes)ほど大げさにしたくないけれど、複数台のDockerホストで冗長化された環境をサクッと作りたい。そんな現場でDocker Swarmは今でも強力な相棒です。
この記事では、Docker Swarmの基本から、実運用で必ず直面する「コンテナが起動しない」「ノードが切断される」といったトラブルの解決策まで、現場の知見をたっぷり詰め込んで逆引き形式で解説します。これをマスターすれば、日々のインフラ運用や突発的なトラブル対応が劇的に楽になりますよ。肩の力を抜いて、一緒に見ていきましょう!
—
1. Docker Swarmってそもそも何をするもの?(ツールの役割)
Docker Swarmは、Docker社が提供するネイティブなコンテナオーケストレーションツールです。
一言で言うと、「複数のDockerサーバーを1つの巨大な仮想サーバーに見立てて、コンテナの配置や数を自動で管理してくれる仕組み」です。
Kubernetesとの違いは?
よく「Kubernetes(K8s)と何が違うの?」と聞かれます。K8sは非常に高機能ですが、学習コストや初期セットアップの重さ(オーバーヘッド)がなかなかのものです。
一方、Docker Swarmは「すでにDockerを使っている環境なら、追加のソフトをほとんど入れずに、数分でクラスタを組める」という圧倒的な手軽さがあります。小規模〜中規模のシステムや、エッジデバイスの管理などにおいて、今でも最高の選択肢の一つです。
—
2. 5分で完了!基本のインストールとセットアップ
Docker Swarmを使うために、何か特別なものをインストールする必要はありません。Dockerがインストールされていれば、Swarm機能はすでに標準で入っています。
ここでは、手元に2台のサーバー(または仮想マシン)がある想定で話を進めます。
- マネージャーノード(司令塔): `192.168.1.10`
- ワーカーノード(働き手): `192.168.1.11`
Step 1: マネージャーノードを初期化する
まずは司令塔となるサーバーで以下のコマンドを実行します。
マネージャーとしてSwarmを初期化する
docker swarm init –advertise-addr 192.168.1.10
実行すると、画面に長文のメッセージと、「ワーカーノードに参加するためのコマンド」が表示されます。この出力結果(特に `docker swarm join …` の部分)はメモしておきましょう。
Step 2: ワーカーノードをクラスタに参加させる
次に、働き手となるサーバー(192.168.1.11)にログインし、先ほどメモしたコマンドを実行します。
マネージャーから発行されたトークンを使ってクラスタに参加
docker swarm join –token <マネージャーから渡されたトークン> 192.168.1.10:2377
「This node joined a swarm as a worker.」と表示されたら成功です!
Step 3: 動作確認(HelloWorld的アプローチ)
マネージャーノードに戻り、現在のクラスタの状態を確認してみましょう。
docker node ls
これで、マネージャーとワーカーが一覧表示され、状態が `Ready` になっていれば基礎セットアップは完璧です。おめでとうございます!これであなたもSwarm使いの仲間入りです。
—
3. 【逆引きトラブルシューティング】現場で震えるエラーと解決の全手法
ここからが本番です。実運用でよくあるトラブルと、その具体的な処方箋を逆引きで解説します。
—
トラブル1: `No suitable node (image not found)`
【症状】
サービスをデプロイしたのに、コンテナがいつまで経っても起動せず、タスクのステータスを見ると「No suitable node (image not found)」というエラーで止まっている。
【原因】
Swarmのワーカーノードが、指定されたDockerイメージをローカルに持っていない、またはDocker Hubなどのレジストリからダウンロード(Pull)できていない状態です。マネージャー側だけにイメージがあって、ワーカー側にない場合に頻発します。
【解決策】
1. プライベートレジストリを使う場合:
各ノードがそのレジストリにログイン(`docker login`)しているか確認します。
2. ローカルビルドしたイメージの場合:
Swarmでは、マネージャーでビルドしたイメージは自動的にワーカーに同期されません。すべてのノードに同じイメージを配備するか、内部レジストリを立ててそこからPullさせる必要があります。
# 例:各ノードで事前にイメージをpullしておく
docker pull your-registry.com/your-app:latest
3. –pull オプションを活用する:
サービスを作成する際に、常に最新のイメージを自動で取得するよう指示します。
docker service create –name my-web –pull always -p 80:80 nginx:latest
—
トラブル2: ノードが突然「Down」または「Unreachable」になる
【症状】
`docker node ls` を実行した際、特定のワーカーノードの状態が `Down` や `Unreachable` に変わっており、そこで動いていたコンテナが別のノードに勝手に再配置(フェイルオーバー)されている。
【原因】
マネージャーとワーカー間の通信障害、またはサーバーの過負荷によるフリーズが主な原因です。Docker Swarmは、デフォルトで一定時間(約10秒〜数分)ノードからの応答がないと「死んだ」とみなします。
【解決策】
1. ネットワークポートの確認(セキュリティグループ / ファイアウォール)
Swarmの通信には以下のポートが必須です。クラウド環境(AWSやGCPなど)のセキュリティグループで塞がれていないか確認してください。
- TCP `2377` (Swarm管理用)
- TCP/UDP `7946` (ノード間通信用)
- UDP `4789` (オーバーレイネットワーク用)
2. 死活監視のタイムアウトを調整する
一時的な高負荷でノードが切断判定されてしまう場合は、デーモンのハートビート間隔を調整することも可能です(※基本はネットワークやリソース不足の根本原因を直すことが先決です)。
—
トラブル3: コンテナ間で通信ができない(オーバーレイネットワークの罠)
【症状】
複数のコンテナをデプロイしたが、別々のノードに配置されたコンテナ同士が、お互いのホスト名やIPアドレスで通信できない。
【原因】
通常のブリッジネットワークではなく、Swarm用のオーバーレイネットワーク(overlay)が正しく作成されていない、またはサービス作成時にネットワークの指定が漏れている。
【解決策】
1. オーバーレイネットワークを明示的に作成する
必ず `–driver overlay` を指定してネットワークを作成します。
docker network create –driver overlay my-overlay
2. サービス作成時にネットワークをアタッチする
docker service create \
–name my-app \
–network my-overlay \
nginx:latest
これで、Swarmの内部DNSが自動的に解決され、コンテナ名だけで通信できるようになります。
—
トラブル4: サービスのアップデートが反映されない(ロールアウトのスタック)
【症状】
イメージのタグを新しくして `docker service update` を実行したのに、古いバージョンのままコンテナが動き続けている。
【原因】
イメージのハッシュ値(ダイジェスト)が変わっていない場合、Dockerは「変更がない」と判断してアップデートをスキップします。特に `:latest` タグを使い回しているときに発生しがちです。
【解決策】
強制的にイメージを再取得させながらアップデートを実行します。
–image オプションで明示的にイメージを指定し、–force をつける
docker service update –image nginx:latest –force my-app
また、実運用では `:latest` ではなく、Gitのコミットハッシュやセマンティックバージョニング(例: `v1.2.3`)のタグを必ず使うのが、プロとしての鉄則です。
—
4. 先輩エンジニアからのアドバイス:日常運用を楽にする心得
Docker Swarmは、シンプルゆえに「手動でゴリゴリ操作する」こともできてしまいます。しかし、本番環境を安定稼働させるためには、「Infrastructure as Code(IaC)」の精神を忘れないでください。
- コマンドを直接叩いて構築するのではなく、Docker Composeファイル(version 3以降)を書き、`docker stack deploy` 命令で宣言的にインフラを管理しましょう。
- 「これさえあればいつでも環境を再構築できる」という状態をコードで作っておくことが、夜中に起こされる悪夢を防ぐ最大の防衛策です。
宣言的な設定ファイルの例(docker-stack.yml)
version: ‘3.8’
services:
web:
image: nginx:alpine
deploy:
replicas: 3
restart_policy:
condition: on-failure
ports:
- “80:80”
トラブルが起きても、今回ご紹介した原因とコマンドの引き出しがあれば、冷静に対処できるはずです。
毎日のインフラ運用が、少しでもラクで楽しいものになりますように。応援しています!