はじめに
自宅サーバーでNginx Proxy Manager(NPM)を使用していたところ、host.docker.internal
を使った内部サービスへのプロキシ設定で502 Bad Gatewayエラーが発生。原因調査と解決策として、TraefikへのProxyツール移行を実施した記録です。
問題の概要
環境
- Ubuntu Server 22.04
- Docker Compose
- 内部ネットワーク(192.168.2.0/24)
- 対象アプリ:ポート17681で動作
発生した問題
# Nginx Proxy Managerの設定
extra_hosts:
- "host.docker.internal:192.168.2.40"
上記設定にも関わらず、ブラウザアクセス時に502エラーが発生。
原因調査結果
# コンテナ内からの接続テスト
$ docker-compose exec app curl -s -o /dev/null -w "%{http_code}" http://host.docker.internal:17681
200 # ← 接続成功
# エラーログ確認
$ docker-compose exec app cat /data/logs/proxy-host-1_error.log
host.docker.internal could not be resolved (3: Host not found)
根本原因:Nginxワーカープロセスがhost.docker.internal
の名前解決に失敗
解決策:Traefikへの移行
なぜTraefikを選んだか
項目 | Nginx Proxy Manager | Traefik |
---|---|---|
内部エンジン | Nginx | Go言語独自実装 |
名前解決 | Nginxの制約あり | Docker統合優秀 |
設定方法 | Web UI | ファイル/ラベル |
学習コスト | 低 | 中 |
Traefik導入手順
1. ディレクトリ構成
sudo mkdir -p /opt/traefik/dynamic
cd /opt/traefik
2. Docker Compose設定
# docker-compose.yml
services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "8080:8080" # Web UI
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./dynamic:/etc/traefik/dynamic:ro
extra_hosts:
- "host.docker.internal:192.168.2.40"
3. Traefik基本設定
# traefik.yml
api:
dashboard: true
insecure: true
entryPoints:
web:
address: ":80"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
directory: /etc/traefik/dynamic
watch: true
log:
level: INFO
4. プロキシ設定(動的ファイル)
# dynamic/services.yml
http:
routers:
web-terminal:
rule: "Host(`web-terminal.gpuserver.lan`)"
service: web-terminal-service
entryPoints:
- web
services:
web-terminal-service:
loadBalancer:
servers:
- url: "http://host.docker.internal:17681"
5. systemd自動起動設定
# /etc/systemd/system/traefik.service
[Unit]
Description=Traefik Proxy
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/traefik
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable traefik.service
sudo systemctl start traefik.service
動作確認
Web UI確認
http://192.168.2.40:8080/dashboard/
HTTP Routersにweb-terminal@file
が表示されることを確認。
プロキシ動作確認
http://web-terminal.gpuserver.lan
正常にアプリケーションにアクセスできることを確認。
トラブルシューティング
よくある問題と対処法
1. ポート競合エラー
# NPMが動いている場合は停止
cd /opt/nginx-proxy-manager
sudo docker-compose down
2. YAMLシンタックスエラー
# 設定ファイルの確認
sudo docker logs traefik --tail 10
# よくある間違い:URLの末尾にコロン
- url: "http://host.docker.internal:17681": # ← NG
- url: "http://host.docker.internal:17681" # ← OK
3. 設定が反映されない
# ファイル存在確認
sudo docker exec traefik ls -la /etc/traefik/dynamic/
# 権限確認
sudo chmod 644 traefik.yml dynamic/services.yml
追加サービスの設定例
新しいサービスを追加する場合:
# dynamic/services.yml に追加
http:
routers:
web-terminal:
rule: "Host(`web-terminal.gpuserver.lan`)"
service: web-terminal-service
entryPoints:
- web
# 新しいサービス
portainer:
rule: "Host(`portainer.gpuserver.lan`)"
service: portainer-service
entryPoints:
- web
services:
web-terminal-service:
loadBalancer:
servers:
- url: "http://host.docker.internal:17681"
# 新しいサービス
portainer-service:
loadBalancer:
servers:
- url: "http://host.docker.internal:9000"
ファイル保存後、自動的に設定が反映されます(watch: true
のため)。
まとめ
移行のメリット
✅ host.docker.internal
の名前解決問題が解決
✅ 設定ファイルによるバージョン管理が可能
✅ ホットリロード対応(設定変更時に再起動不要)
✅ Docker統合が優秀
移行のデメリット
❌ Web UIでの設定変更不可(読み取り専用)
❌ 学習コストが若干高い
❌ GUIでの直感的操作ができない
適用場面
- Infrastructure as Codeを重視する環境
- 設定の変更頻度が低い環境
- Docker環境での内部プロキシ
Web UIでの設定管理を重視する場合は、ZoraxyやCaddyなど他の選択肢も検討することをお勧めします。