Dockerネットワークとは

Dockerネットワークは、コンテナ間やホストとの通信を管理する仕組みです。

ネットワークでできること

  • 🔗 コンテナ同士の通信
  • 🌐 ホストからコンテナへのアクセス
  • 🔒 ネットワークの分離(セキュリティ)
  • 🚀 複数ホスト間でのコンテナ接続
  • ⚙️ カスタムDNS設定

ネットワークドライバーの種類

1. bridge(デフォルト)

# 同一ホスト内のコンテナ間通信
docker network create my-network

特徴:
✅ 最も一般的
✅ コンテナ間で名前解決可能
✅ ポート公開でホストからアクセス
🎯 用途: 通常のアプリケーション

2. host

# ホストのネットワークを直接使用
docker run --network host nginx

特徴:
✅ ネットワークオーバーヘッドなし
⚠️ ポート衝突の可能性
⚠️ コンテナ間の分離がない
🎯 用途: パフォーマンス重視

3. none

# ネットワークなし
docker run --network none alpine

特徴:
✅ 完全に分離
⚠️ 外部通信不可
🎯 用途: セキュリティ重視、バッチ処理

4. overlay

# 複数ホスト間でのネットワーク(Docker Swarm)
docker network create --driver overlay my-overlay

特徴:
✅ 複数ホストをまたぐ通信
✅ Swarmモードで使用
🎯 用途: マイクロサービス、クラスタ

ネットワークの基本操作

ネットワーク作成

# デフォルト(bridge)
docker network create my-network

# サブネット指定
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  my-custom-network

# IPv6対応
docker network create \
  --ipv6 \
  --subnet 2001:db8:1::/64 \
  my-ipv6-network

ネットワーク一覧

# すべてのネットワーク
docker network ls

# フィルタ
docker network ls --filter driver=bridge

ネットワーク詳細

docker network inspect my-network

[
    {
        "Name": "my-network",
        "Driver": "bridge",
        "IPAM": {
            "Config": [{
                "Subnet": "172.20.0.0/16",
                "Gateway": "172.20.0.1"
            }]
        },
        "Containers": {
            "container_id": {
                "Name": "web",
                "IPv4Address": "172.20.0.2/16"
            }
        }
    }
]

ネットワーク削除

# 特定のネットワーク
docker network rm my-network

# 未使用ネットワークをすべて削除
docker network prune

コンテナのネットワーク接続

起動時にネットワーク指定

# ネットワーク指定
docker run -d \
  --name web \
  --network my-network \
  nginx

# 複数ネットワークに接続
docker run -d \
  --name proxy \
  --network frontend \
  --network backend \
  nginx

実行中のコンテナをネットワークに接続

# ネットワークに接続
docker network connect my-network web

# IPアドレス指定
docker network connect --ip 172.20.0.10 my-network web

# ネットワークから切断
docker network disconnect my-network web

コンテナ間通信

名前によるDNS解決

# docker-compose.yml
version: '3.8'

services:
  web:
    image: nginx
    networks:
      - app-network
  
  api:
    image: node:18-alpine
    command: sh -c "curl http://web"  # web という名前で通信可能
    networks:
      - app-network

networks:
  app-network:

エイリアス(別名)の設定

version: '3.8'

services:
  db:
    image: postgres:15
    networks:
      app-network:
        aliases:
          - database
          - postgres-server
  
  app:
    image: myapp
    command: sh -c "ping database"  # エイリアスで接続可能
    networks:
      - app-network

networks:
  app-network:

ポート公開

ポートマッピングの基本

# ホストポート:コンテナポート
docker run -p 8080:80 nginx

# 複数ポート
docker run -p 8080:80 -p 8443:443 nginx

# IPアドレス指定
docker run -p 127.0.0.1:8080:80 nginx  # localhostのみ

# ランダムポート(ホスト側)
docker run -p 80 nginx  # ホストの空きポートが自動割り当て

公開ポートの確認

# コンテナのポート確認
docker port container_name

# 例:
80/tcp -> 0.0.0.0:8080
443/tcp -> 0.0.0.0:8443

docker-compose でのポート設定

version: '3.8'

services:
  web:
    image: nginx
    ports:
      - "8080:80"      # 短い形式
      - "8443:443"
      - "127.0.0.1:9000:9000"  # IPアドレス指定
      - target: 5000   # 長い形式
        published: 5000
        protocol: tcp
        mode: host

実用的なネットワーク構成

フロントエンド・バックエンド分離

version: '3.8'

services:
  nginx:
    image: nginx
    ports:
      - "80:80"
    networks:
      - frontend
  
  api:
    image: node:18-alpine
    networks:
      - frontend
      - backend
  
  db:
    image: postgres:15
    networks:
      - backend  # フロントエンドから直接アクセス不可
    environment:
      POSTGRES_PASSWORD: password

networks:
  frontend:
  backend:

リバースプロキシ構成

version: '3.8'

services:
  nginx:
    image: nginx
    ports:
      - "80:80"
      - "443:443"
    networks:
      - proxy
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
  
  app1:
    image: myapp1
    networks:
      - proxy
    expose:
      - "3000"  # ホストには公開しない、proxyネットワーク内のみ
  
  app2:
    image: myapp2
    networks:
      - proxy
    expose:
      - "4000"

networks:
  proxy:

nginx.confの例

upstream app1 {
    server app1:3000;
}

upstream app2 {
    server app2:4000;
}

server {
    listen 80;
    server_name app1.example.com;
    
    location / {
        proxy_pass http://app1;
    }
}

server {
    listen 80;
    server_name app2.example.com;
    
    location / {
        proxy_pass http://app2;
    }
}

カスタムDNS設定

DNSサーバーの指定

# コンテナ起動時
docker run \
  --dns 8.8.8.8 \
  --dns 1.1.1.1 \
  alpine

# docker-compose
version: '3.8'

services:
  app:
    image: alpine
    dns:
      - 8.8.8.8
      - 1.1.1.1
    dns_search:
      - example.com

hostsファイルの追加

# /etc/hosts に追加
docker run \
  --add-host myhost:192.168.1.100 \
  alpine

# docker-compose
services:
  app:
    image: alpine
    extra_hosts:
      - "myhost:192.168.1.100"
      - "db:172.20.0.5"

静的IPアドレスの設定

カスタムネットワークで固定IP

# ネットワーク作成
docker network create \
  --subnet 172.20.0.0/16 \
  my-network

# 固定IP指定
docker run -d \
  --name web \
  --network my-network \
  --ip 172.20.0.10 \
  nginx

docker run -d \
  --name db \
  --network my-network \
  --ip 172.20.0.20 \
  postgres

docker-composeで固定IP

version: '3.8'

services:
  web:
    image: nginx
    networks:
      app-network:
        ipv4_address: 172.20.0.10
  
  db:
    image: postgres:15
    networks:
      app-network:
        ipv4_address: 172.20.0.20

networks:
  app-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
          gateway: 172.20.0.1

ネットワークのデバッグ

コンテナのネットワーク情報確認

# コンテナのIPアドレス確認
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name

# すべてのネットワーク情報
docker inspect container_name | jq '.[0].NetworkSettings'

疎通確認

# コンテナから別のコンテナへping
docker exec web ping api

# curlでHTTP確認
docker exec web curl http://api:3000

# nslookupでDNS確認
docker exec web nslookup api

デバッグコンテナの起動

# ネットワークツールが入ったコンテナ
docker run --rm -it \
  --network my-network \
  nicolaka/netshoot

# 中で使えるツール:
# - ping
# - curl
# - nslookup
# - netstat
# - tcpdump

セキュリティ

ネットワークの分離

# 外部に公開するサービスのみfrontend
# データベースはbackendのみ

services:
  nginx:
    networks: [frontend]
  
  api:
    networks: [frontend, backend]
  
  db:
    networks: [backend]  # 外部から直接アクセス不可

ファイアウォールルール

# iptables でDocker通信を制限
sudo iptables -I DOCKER-USER -s 172.20.0.0/16 -d 172.30.0.0/16 -j DROP

# 特定のポートのみ許可
sudo iptables -I DOCKER-USER -p tcp --dport 443 -j ACCEPT

パフォーマンス

hostネットワークの使用

# 最高のパフォーマンス(Linuxのみ)
docker run --network host nginx

# ただしポートの分離なし

MTU設定

# ネットワークのMTU調整
docker network create \
  --opt com.docker.network.driver.mtu=1450 \
  my-network

トラブルシューティング

コンテナ間で通信できない

1. 同じネットワークに接続しているか確認
docker network inspect my-network

2. ファイアウォールを確認
sudo iptables -L DOCKER-USER

3. DNS解決を確認
docker exec container1 ping container2

4. ポートが開いているか確認
docker exec container2 netstat -tlnp

ポートが既に使用されている

# 使用中のポートを確認
sudo lsof -i :8080
sudo netstat -tlnp | grep 8080

# プロセスを停止するか、別のポートを使用

DNSが解決されない

# デフォルトのbridgeネットワークではDNS解決不可
# カスタムネットワークを作成
docker network create my-network
docker run --network my-network --name web nginx
docker run --network my-network alpine ping web

まとめ

Dockerネットワークを理解して安全で効率的なコンテナ通信を実現できます。

重要ポイント

  • 本番環境ではカスタムネットワークを使う
  • ネットワークを分離してセキュリティ向上
  • コンテナ名でDNS解決(bridgeネットワーク)
  • 必要なポートのみ公開
  • hostネットワークは慎重に

ベストプラクティス

  • フロントエンド・バックエンドでネットワーク分離
  • データベースは外部に公開しない
  • 静的IPは開発環境のみ
  • docker-composeでネットワーク管理