0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Docker SwarmのOverlayネットワークを使ったWebサービス構築+NginxでIPが取れない話

Posted at

この記事では、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が取得できます。

ステップ:

  1. NginxはSwarmの外で動かす(ホスト上や別VM)
  2. Swarm内のWebサービスを mode: host でポート公開
  3. 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を使う(中級者向け)

  • TraefikHAProxy を使い、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透過性」がない点は注意!
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?