Docker Swarmとは?
ここで学べること
Docker Swarmは、複数のノード(物理マシンまたは仮想マシン)をひとつの統合システムとして管理するためのコンテナオーケストレーションツールであり、Dockerにネイティブに組み込まれたアプリケーションモードの一部として提供されています。
Swarmを構成する各ノードは互いに接続されており、物理的なマシンでも仮想マシンでも構いません。その役割に応じて、ノードは次の2種類に分類されます。
- マネージャーノード(Manager nodes): Swarm全体を制御する「Swarmマネージャー」プロセスを実行します。 これは、Swarmモードで発行されたコマンドを処理し、クラスタの理想的な状態(desired state)と実際の状態(actual state)を同期させる役割を担います。
- ワーカーノード(Worker nodes): システムの実際のワークロード(コンテナ)を実行するノードです。

これらは、Raftコンセンサスや分散ステートなどの技術を含む**分散システムをオーケストレーションするためのツール群「Swarmkit」**によって実現されます。SwarmkitはDockerに統合されています。
Docker Swarmを使う理由
DockerをSwarmモードを使わずに実行する場合と比べて、Docker Swarm は本番環境でのワークロード実行においていくつかの利点を提供します。
利点
高可用性:Docker Swarmは、複数のノードとワーカーノードからなる「Swarm構成」により、高可用な環境を実現します。 SwarmkitのRaftコンセンサスアルゴリズムを使用して、ノード間の信頼性の高い通信とフォールトトレランス(障害耐性)を確立します。 高可用な環境を構築するには、少なくとも 3つのマネージャーノード が必要で、1ノードの障害に耐えられる構成になります。 推奨構成は 7つのマネージャーノード で、最大3ノードの同時障害に対応可能です。
負荷分散:複数のワーカーノードが存在するため、Swarm内でアプリケーションの複数インスタンスをデプロイできます。 マネージャーノードによる内部ロードバランシング機構によって、リクエストがワーカーノード間に均等に分配されます。 また、Swarmマネージャーはヘルスチェックやレディネスチェックを通じて、サービスが正常に稼働していることを監視します。
シンプルさ: Dockerのエコシステムは、運用の俊敏性、移植性、コスト効率を高めます。 特にDocker SwarmモードはDocker本体に統合されているため、追加のツールを導入する必要がありません。 Docker CLI(コマンドラインインターフェース)には、Swarmモード・非Swarmモードの両方でアプリやコンテナを簡単に管理するためのコマンドとオプションが含まれています。 また、学習コストが高いKubernetes(K8s)と比較して、Docker Swarmモードは導入・運用がより簡単 です。
一般的なユースケース
Docker Swarmモードは、小規模から中規模のデプロイ構成 に適しています。たとえば、1つのデータベース、Webアプリ、キャッシュサービス、いくつかのバックエンドサービスで構成される小規模なアプリケーションスタックなどが該当します。
一方で、より大規模なデプロイでは、保守性、カスタマイズ性、災害復旧(DR)対応 といった要件において制約が生じる可能性があります。また、自動化や複雑な障害耐性よりも、サービスの高可用性や自動負荷分散を優先したい場合 にもDocker Swarmは適しています。
総じて、組織がコンテナ環境への移行を検討している場合、管理と運用がシンプルなDocker Swarmは導入しやすい選択肢 となります。
なぜ他のコンテナオーケストレーターではなく Docker Swarm を使うのか?
前述のとおり、Docker Swarm を使用する主な利点の一つは、より高度なコンテナオーケストレーションツールである Kubernetes(K8s)と比べて学習コストが低いことです。Docker をインストールするだけで、必要なツールやサービスが利用可能になります。複数ノードを立ち上げたい場合は、VirtualBox や Vagrant を使って簡単に環境を構築でき、いくつかのコマンドを実行するだけでクラスターを作成できます。さらに、Docker に備わっている既存のオプションを利用する以外に特別な設定変更を行う必要もありません。
また、運用環境でも、比較的管理が容易な構成(例えば 3〜10 ノードで 100 コンテナ未満の稼働)であれば、Docker Swarm を使用することが可能です。しかし、より大規模なワークロードになると、Docker Swarm はすぐに K8s に劣るようになります。K8s にはその規模に対応した優れたツール、サポート、そしてドキュメントが揃っているためです。
基本概念
Docker Swarm モードで作業する際に理解しておくべき主要な概念には、次のようなものがあります。
Swarm(スウォーム)
Swarm は、信頼性の高い運用を実現するために互いに連携するノード群で構成されます。ノードを Swarm(群)として構成することで、ノードが合意形成(コンセンサス)を行い、単一障害点(Single Point of Failure)のリスクを軽減できます。任意の時点で、マネージャーノードの中から 1 つのリーダーノードが選出され、Swarm 全体に関する重要な意思決定を行います。もしリーダーノードが利用不能になった場合は、残りのノードが合意のもとで新しいリーダーを選出し、障害が発生したノードの役割を引き継ぎます。
Node(ノード)
ノードとは、Swarm モードで動作する Docker Engine のインスタンスを 1 つ実行している物理または仮想マシンのことです。設定に応じて、このインスタンスは ワーカーノード(worker node) または マネージャーノード(manager node) として動作します。
- ワーカーノード は、デプロイメントやサービスなどのワークロードを受け入れて実行する役割を担います。
- マネージャーノード は Swarm の制御プレーン(control plane)として機能し、サービスのオーケストレーション、コンセンサスへの参加、ワークロードのスケジューリングなどを担当します。
高可用性と信頼性を確保するためには、これら両方のタイプのノードを十分な数だけ配置することが重要です。
サービスとタスク
Swarm 内で実行されるワークロードや処理は、2 種類に分けられます。
サービス(Service) は、特定の条件に基づいてデプロイされるコンテナの定義です。Swarm モードでは、各ノードに 1 つずつインスタンスを実行する グローバルサービス(global service)(例:監視やログ収集コンテナ)や、複数インスタンスを展開してスパイク的な負荷に対応する レプリケートサービス(replicated service) をデプロイできます。Swarm にデプロイされたサービスは、docker service scale コマンドを使ってスケールアップ/スケールダウンが可能であり、同じクラスター内の任意のノードから内部 DNS 解決を通じてアクセスできます。
タスク(Task) は、特定のノードに割り当てられる単一のワークロード定義です。タスクを Docker Swarm に送信すると、そのタスクは 1 つのノード上で実行されます。同じ ID を持つタスクを他のノードで実行することはできません。タスクを作成するには、まず希望するデプロイメント内容を定義した サービス を作成すれば、対応するタスクが自動的に生成され、実際の処理を実行します。
タスクにはライフサイクル上の状態が割り当てられており、たとえば以下のような状態を取ります:
- NEW:新しく作成された状態
- PENDING:割り当て待ちの状態
- COMPLETE:正常に完了した状態
Load Balancing(ロードバランシング)
ロードバランシングとは、サービスへのリクエストの流れを均等に分散させる仕組みのことです。
たとえば、スーパーボウルの時期のようにアクセスが急増し、多くの人が同じウェブサイトを訪れる状況では、アクセスを複数のウェブサイトインスタンスに分散する必要があります。こうすることで、すべての訪問者が同等のサービス品質を体験できるようにします。Docker Swarm では、自動ロードバランシング機能 が標準で組み込まれており、追加の設定なしで利用できます。また、HAProxy や NGINX などの外部ロードバランサーに対して、サービスのポートを簡単に公開できる仕組みも備えています。
ユースケース例
Swarm を使った実験を行うには、少なくとも 1 つのマネージャーノード と 2 つのワーカーノード が必要です。ここでは、そのために用意された簡単な Vagrantfile を利用します。このファイルは 4 台の仮想マシン(VM)を起動し、初期化スクリプトの中で Docker を自動的にインストールするようになっています。
まず、仮想マシンを起動します。
$ vagrant up
すべてのマシンの準備が整ったら、マネージャーノードに参加します。
$ vagrant status
Current machine states:
manager running (virtualbox)
worker01 running (virtualbox)
worker02 running (virtualbox)
worker03 running (virtualbox)
$ vagrant ssh manager
vagrant@manager:~$ docker info
Swarmの作成
マネージャーノードで次のコマンドを実行し、Docker Swarm を初期化します。
vagrant@manager:~$ docker swarm init --listen-addr 10.10.10.2:2377 --advertise-addr 10.10.10.2:2377
Swarm initialized: current node (r9xym5ymmzmm7e7ux3f4sxcs9) is now a manager.
ここでは、マネージャーノードのプライベート IP アドレス(10.10.10.2)を使用しています。これは、ワーカーノードの IP アドレス一覧(10.10.10.21、10.10.10.22、10.10.10.23)と同じネットワーク内にあります。
この Swarm にワーカーノードを追加するには、次のコマンドを実行します。
$ docker swarm join --token SWMTKN-1-4w74yys9pihkl9qhmdrk0zlqtca9xrihan36cktdt2du251qxm-bw60iu884vettl2ay65m0y1uy 10.10.10.2:2377
This node joined a swarm as a worker.Code language: JavaScript (javascript)
最初のマネージャーノードを作成した際に、ジョイントークンが表示されました。各ワーカーノード(worker01、worker02、worker03)で同じコマンドを使用するようにしてください。
最後に、マネージャーノードからノードの一覧を確認します。
vagrant@manager:~$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
r9xym5ymmzmm7e7ux3f4sxcs9 * manager Ready Active Leader 20.10.12
r1l8jn1ot24hfzs0f7e9te5u3 worker01 Ready Active 20.10.12
wi7uq4jpcoh8rd7hlej6xuc4b worker02 Ready Active 20.10.12
p7paeu2d72rqu4dr1dllvcdys worker03 Ready Active 20.10.12
ここまでは順調です。
Swarmにサービスをデプロイ
Swarm にサービスをデプロイするには、docker service コマンドを使用してコンテナアプリケーションをプッシュします。replicaの数や、Swarm 外部に公開するサービスのポートなどのパラメータを指定することもできます。
Swarm と同じネットワーク内から、以下のコマンドを実行して NGINX コンテナをすべてのノードに分散配置します。
vagrant@manager:~$ docker service create --name my_nginx --replicas 8 --publish published=8080,target=80 nginx
各ノード内で実行中のコンテナを確認し、localhost:8080 にアクセスできることを確認します。
vagrant@worker02:~$ docker psCode language: JavaScript (javascript)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
de396992a942 nginx:latest "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp my_nginx.2.enp8yy55f0j1u1y8tm44lpxjq
935eea500ce6 nginx:latest "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp my_nginx.6.f8zl2oh530rvfe15cr6fcmae0

また、デプロイしたいサービスを記述した yml 仕様ファイルを使用して、docker stack コマンドを実行することもできます。たとえば、先ほどのコマンドは次の仕様と同等です。
# DockerfileCode language: PHP (php)
version: '3.7'
services:
my_nginx:
image: nginx:latest
deploy:
replicas: 8
ports:
- "8080:8080"vagrant@manager:~$ docker stack deploy -c stack.yml my_nginx
vagrant@manager:~$ docker stack services my_nginx
ID NAME MODE REPLICAS IMAGE PORTS
l8op85m1kaoy my_nginx_my_nginx replicated 8/8 nginx:latest *:8080->8080/tcp
他の役立つコマンド
Swarm モードでは、いくつかの便利なコマンドを使用できます。ここではその一部を簡単に見てみましょう。
ノードの状態を確認する:ノード情報を確認するには、docker node inspect コマンドを使用します。
vagrant@manager:~$ docker node inspect worker02Code language: JavaScript (javascript)
[
{
"ID": "wi7uq4jpcoh8rd7hlej6xuc4b",
"Version": {
"Index": 35
},
"CreatedAt": "2023-02-15T12:28:39.485382607Z",
"UpdatedAt": "2023-02-16T10:16:47.28165702Z",
…
マネージャーノードをワーカーノードに降格させる: docker node demote <manager_node_id> コマンドを使用すると、マネージャーをワーカーに降格させることができます。
ワーカーノードをマネージャーノードに昇格させる: 逆に、docker node promote コマンドを使用すると、ワーカーノードをマネージャーノードに昇格させることができます。
vagrant@manager:~$ docker node promote worker01
Node worker01 promoted to a manager in the swarm.
vagrant@manager:~$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
r9xym5ymmzmm7e7ux3f4sxcs9 * manager Ready Active Leader 20.10.12
r1l8jn1ot24hfzs0f7e9te5u3 worker01 Ready Active Reachable 20.10.12
wi7uq4jpcoh8rd7hlej6xuc4b worker02 Ready Active 20.10.12
p7paeu2d72rqu4dr1dllvcdys worker03 Ready Active 20.10.12
Draining a node(ノードのドレイン): ノードをドレインするとは、Swarm エンジンがそのノードで稼働中のコンテナを他のワーカーノードへ移動させることを意味します。これは、ノードのアップグレードを予定している場合や、新しいワークロードを受け入れる前にノードの健全性を確認したい場合に便利です。
vagrant@manager:~$ docker node update --availability drain worker02Code language: JavaScript (javascript)
vagrant@manager:~$ docker node inspect worker02 --format '{{ .Spec.Availability }}'
Drain
次のコマンドを実行すると、ノードを再びアクティブな状態に戻すことができます。
vagrant@manager:~$ docker node update --availability active worker02
worker02
まとめ
以上で、Docker Swarm モードとその運用機能の概要説明は終了です。
Docker Swarm は、そのシンプルさ、自動ロードバランシング機能、そしてスムーズなセットアップによって、K8s に対する魅力的な代替手段となります。Docker Swarm モードは Docker に組み込まれているため、追加の技術を学ばなくてもすぐに試すことができます。総じて、Docker Swarm モードは高可用性を備えたレプリケートサービスのデプロイを、より簡単かつ効率的に行うことを可能にします。
