この記事では、Docker SwarmのOverlayネットワークの仕組みを、Nginx・Webアプリ・DB構成の実例を通してわかりやすく解説します。
さらに、実際に構築してみると気づくのが...
「Nginxでクライアントの本当のIPが取れない問題」
その原因と対策までカバーします!
🛠️ システム構成
今回は以下のような3サービス構成をSwarm上に構築します:
サービス | 説明 |
---|---|
nginx |
外部からのHTTPリクエストを受けるリバースプロキシ |
web |
Webアプリケーション(例:Flask, Node.js) |
db |
データベース(MySQLなど) |
🖼️ ネットワーク構成(Mermaid)
3つのサービスは overlay
ドライバを使用した仮想ネットワーク app_net
に接続されています。
📦 docker-compose.yml
(Swarm用)
version: "3.9"
services:
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- app_net
web:
image: my-web-app
networks:
- app_net
db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: example
networks:
- app_net
networks:
app_net:
driver: overlay
⚠️ NginxではクライアントIPが取得できない理由
Swarmでは、**Ingressネットワーク(IPVS経由)**を介してサービスへリクエストがルーティングされます。このとき、クライアントの元IPは、SwarmのルーティングノードのIPに上書きされてしまいます。
つまり、$remote_addr
はこんな感じになります:
SwarmのノードIP(例:10.0.0.x) → ❌ クライアントのグローバルIPではない
Nginxログの例:
10.0.0.2 - - [19/May/2025:15:00:00 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.79.1"
本当のIP(例:203.0.113.25)ではない!
💡 解決策1:Swarmの外にNginxを出す
Swarmの外部でNginxをホストして、Swarm内のWebアプリにプロキシする構成にすることで、真のIPが取得できます。
ステップ:
- NginxはSwarmの外で動かす(ホスト上や別VM)
- Swarm内のWebサービスを
mode: host
でポート公開 - NginxはSwarmノードのIPとポートへ
proxy_pass
location / {
proxy_pass http://192.168.1.101:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
💡 解決策2:PROXY protocolを使う(中級者向け)
-
Traefik
やHAProxy
を使い、PROXY protocol
を通して本当のIPを転送 - Nginx側でも
proxy_protocol
を有効にする必要あり - 手間はかかるが、Swarm内部でもクライアントIPを維持できる
📌 Overlayネットワークのまとめ
特徴 | 内容 |
---|---|
分散仮想ネットワーク | ノード間をまたいだ通信を仮想化 |
自動名前解決 | サービス名でコンテナにアクセスできる |
暗号化可能 | VXLANベースのトンネル通信(希望すればTLS可) |
スケーリング対応 | Webアプリを拡張してもネットワーク構成を維持 |
🧪 おすすめの構成
構成 | メリット |
---|---|
外部Nginx + Swarm Webサービス直アクセス(mode: host) | 最も簡単に本当のIPが取れる |
Traefik or HAProxy + PROXY Protocol | 内部完結できるが設定は複雑 |
📘 まとめ
- Docker SwarmではOverlayネットワークで分散コンテナがつながる
- NginxをSwarm内に置くと、クライアントIPが取得できない
- 対策は「外に出す」or「PROXY protocol」
🙋♂️ 補足
- SSL終端を外部Nginxでやる構成も一般的です
- Overlayネットワーク内でも
service_name:port
で簡単に接続できます - SwarmのIngressバランサは便利だが「IP透過性」がない点は注意!