なぜ小規模チームには今でもDocker Swarmが最適なのか
Kubernetesはコンテナオーケストレーションにおける文なしのヘビー級チャンピオンですが、多くの場合、過剰(オーバーキル)です。基本的なK8sのコントロールプレーンは、最初のアプリケーションをデプロイする前ですら、簡単に2GBのRAMを消費してしまいます。多くのプロジェクトにとって、Kubernetesクラスターを管理することは、原付バイクに乗るためだけに専属の整備士を雇うようなものです。ここでDocker Swarmが本領を発揮します。Dockerエンジンに直接組み込まれており、使い慣れたCompose構文を使用でき、安価な1GBのVPSでもスムーズに動作します。
私はSwarmで3年以上にわたり、最小限のダウンタイムで本番環境のワークロードを管理してきました。これを使えば、専任のDevOpsチームがいなくても、一人の開発者が複数のサーバーにまたがる数十のコンテナを扱うことができます。もしあなたが docker-compose.yml ファイルを書けるなら、Swarmクラスターを実行するために必要なスキルの90%をすでに持っていることになります。
クイックスタート:5分以内でクラスターを構築する
手順を進めるために、2台のLinuxサーバーを用意してください。月額5ドルのエントリーレベルのインスタンスでも十分です。これらを manager-node と worker-node と呼びましょう。
1. マネージャーの初期化
メインサーバーにログインします。次のコマンドを実行して、そのサーバーをクラスターのリーダーに昇格させます。
docker swarm init --advertise-addr <MANAGER-IP>
Dockerは特定の参加(join)コマンドを生成します。それは docker swarm join --token <TOKEN> <IP>:2377 のような形式です。その文字列全体をコピーしてください。
2. ワーカーの参加
2台目のサーバーにSSHでログインし、先ほどコピーしたコマンドを貼り付けます。
docker swarm join --token SWMTKN-1-xyz... 192.168.1.10:2377
3. クラスターの確認
manager-node に戻り、進捗を確認します。
docker node ls
両方のノードが「Ready」ステータスでリストされているはずです。これで、機能的なオーケストレーションクラスターが稼働しました。
アーキテクチャとコアコンセプト
Swarmは、スタンドアロンのDockerとは異なる方法でトラフィックとコンテナのライフサイクルを処理します。個々のコンテナについて考えるのをやめ、サービス(Services)とスタック(Stacks)について考え始めます。
マネージャー vs ワーカー
マネージャーは「頭脳」です。クラスターの状態を管理し、証明書を管理し、サービスをスケジュールします。ワーカーは「筋肉」であり、割り当てられたタスクをただ実行します。マネージャーでもコンテナを実行できますが、大規模な環境ではそれらを分離しておくことで、管理のオーバーヘッドがアプリの速度を低下させるのを防ぐことができます。
ルーティングメッシュ
イングレスルーティングメッシュは、Swarmの秘密兵器です。ポートを公開すると、Dockerはクラスター内のすべてのノードでそのポートを開きます。ユーザーがノードAにアクセスしても、コンテナが実際にはノードCで動作している場合、メッシュが透過的にトラフィックをルーティングします。これにより、基本的なロードバランシングの実装が非常に簡単になります。
オーバーレイネットワーク
Swarmはオーバーレイネットワークを使用して、異なる物理ホスト上のコンテナ同士が安全に通信できるようにします。これは、サーバー間にプライベートな仮想トンネルを作成するようなものです。もはやホスト間で手動でポートをマッピングする必要はありません。代わりに、APIコンテナは db という名前を使用するだけでデータベースコンテナにアクセスできます。
docker network create --driver overlay app-network
スタックを使用したデプロイ
長い docker service create コマンドを手入力するのは間違いの元です。本番環境ではスタック(Stacks)を使用します。スタックファイルは標準のDocker Composeファイルとほぼ同じですが、スケーリングや制約のための deploy セクションが含まれています。
例:スケーラブルなNginxウェブアプリ
これを docker-stack.yml として保存します:
version: '3.8'
services:
web:
image: nginx:latest
networks:
- frontend
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
networks:
- frontend
deploy:
placement:
constraints: [node.role == manager]
networks:
frontend:
driver: overlay
1つのコマンドでスタックをデプロイします:
docker stack deploy -c docker-stack.yml my-app
Swarmは3つのNginxレプリカが維持されるように保証します。ノードがクラッシュした場合、Swarmはその喪失を検出し、残りの正常なハードウェア上に不足しているコンテナを自動的に再作成します。
本番環境から得た貴重な教訓
数年間Swarmを使用してきた中で、これら4つの実践方法がよくある悩みから私を救ってくれました。
1. ネイティブのSecretsを使用する
パスワードを環境変数に含めるのはやめましょう。平文で表示されてしまいます。Swarmに組み込まれたSecretsを使用してください。これらは転送中に暗号化され、コンテナ内のメモリ上( /run/secrets/ )でのみ復号されます。
echo "super-secret-password-123" | docker secret create db_password -
2. 配置制約によるサービスの固定
すべてのノードが同じスペックとは限りません。データベース専用に高速なNVMeドライブを搭載したサーバーが1台あるかもしれません。ノードラベルを使用して、データベースが高速ストレージのある場所に配置されるようにします。
docker node update --label-add storage=nvme node-01
3. 可視化のためにPortainerをインストールする
Swarmには標準のダッシュボードがありません。Portainerはこの欠如を完璧に補います。ログの確認、サービスの再起動、リソース使用状況の監視を行うためのクリーンなウェブインターフェースを提供します。CLIで細かく調べたくない時のトラブルシューティングに不可欠なツールです。
4. ヘルスチェックは必須
中のアプリケーションが完全にフリーズしていても、コンテナが「実行中」であることがあります。必ず healthcheck を定義してください。コンテナがこれらのチェックに応答しなくなると、Swarmはそのコンテナを破棄し、新しいインスタンスを起動します。この自己修復機能こそが、そもそもオーケストレーションを使用する主な理由です。
Docker SwarmにはKubernetesのような巨大なエコシステムはないかもしれませんが、ウェブアプリケーションの80%にとってはこれで十分すぎるほどです。インフラを軽量に保ち、デプロイパイプラインを高速化してくれます。

