Dock Stay
コンテナから外部に繋がらない
動かない時

コンテナから外部に繋がらない

コンテナ内から `apt-get` / `npm install` / 外部 API が届かない問題。bridge / host ネットワーク、DNS 解決、プロキシの順で切り分けます。

コンテナから外部に繋がらない diagram

症状

  • docker build の途中の apt-get update / npm install がタイムアウトする
  • 起動したコンテナから curl https://api.example.com が返ってこない
  • ping はホスト名では通らないが IP 直指定なら通る(DNS 問題)
  • 社内ネットワークや会社 PC からだけ再現する(プロキシ問題)
  • docker compose の別サービス同士は繋がるが、外部は繋がらない

原因

コンテナ → 外部通信が経由する階層を順に疑います。

  1. コンテナ内 DNS: /etc/resolv.conf が適切か。Docker はデフォルトで 8.8.8.8 を入れるが、環境によっては社内 DNS しか解決できないゾーンがある
  2. Docker ブリッジと NAT: 標準の bridge ネットワークはホストの iptables/NAT でインターネットに抜ける。ホストの net.ipv4.ip_forward=0firewalld / ufw がブロックしていると抜けない
  3. ホストのプロキシ設定: 会社 PC では HTTP_PROXY / HTTPS_PROXY が Docker エンジンに伝わらないと docker build / docker pull がまず失敗。コンテナ内アプリにも伝える必要がある
  4. コンテナの DNS 不整合: WSL2 + VPN や macOS + VPN でホスト DNS が途中でブロックされ、コンテナは固有の DNS を使って失敗する
  5. ネットワークモードの選択: docker run --network=host にしているとコンテナの独立ネットワークがないのでホスト側の制限が直撃する

確認コマンド

コンテナ内と外を両方見て、どの層で詰まっているかを特定します。

bash
# ホスト側: 素で外に繋がるか(まずここ)
curl -v https://registry-1.docker.io/v2/
nslookup registry-1.docker.io

# ホスト側: プロキシ環境変数
echo $HTTP_PROXY $HTTPS_PROXY $NO_PROXY

# コンテナ内: DNS 設定
docker run --rm busybox cat /etc/resolv.conf

# コンテナ内: ホスト名 / IP それぞれで到達性
docker run --rm busybox nslookup example.com
docker run --rm busybox ping -c 2 example.com
docker run --rm busybox ping -c 2 93.184.216.34   # example.com の代表 IP

# コンテナ内: HTTP まで届くか
docker run --rm curlimages/curl -v https://api.github.com

# ホストの IP 転送とファイアウォール
sysctl net.ipv4.ip_forward                       # 1 であること
sudo iptables -L -n -v | head -40                # FORWARD チェインが DROP していないか

# Docker の使っているネットワーク一覧と詳細
docker network ls
docker network inspect bridge

解決策

  • DNS を明示的に指定する: 一時的に docker run --dns=8.8.8.8 --dns=1.1.1.1 ...、恒久化するなら /etc/docker/daemon.json"dns": ["8.8.8.8", "1.1.1.1"] を書いて Docker デーモンを再起動
  • 社内 DNS しか使えない環境: 社内 DNS の IP を daemon.jsondns に入れ、同時に search で社内ドメインサフィックスを指定する
  • IP フォワーディングが無効: sudo sysctl -w net.ipv4.ip_forward=1、永続化は /etc/sysctl.d/99-docker.conf
  • プロキシが必要な環境:
    • Docker デーモン向け: /etc/systemd/system/docker.service.d/http-proxy.confEnvironment="HTTP_PROXY=..." などを書いて systemctl daemon-reload && systemctl restart docker
    • docker build 向け: ~/.docker/config.jsonproxies セクションで設定するとビルド引数として自動で渡る(Docker 20.10+)
    • コンテナ実行向け: docker run -e HTTP_PROXY=... -e HTTPS_PROXY=... -e NO_PROXY=localhost,127.0.0.1,.local
  • ネットワークモードを見直す:
    • 外部通信が主: デフォルトの bridge で十分
    • 複数コンテナ同士の名前解決が必要: docker network create mynet してそこに参加させる(Compose なら自動)
    • ホストのポート・パフォーマンスが必要で安全性が担保できる: --network=host(Linux のみ有効)
  • WSL2 + VPN 問題: .wslconfignetworkingMode=mirrored か、VPN 側で WSL2 のサブネットを除外設定にする
  • docker compose で外部だけ切れるとき: Compose が作る <project>_default ブリッジネットワークが NAT できていないケース。docker network inspect <project>_defaultGateway が妥当か確認し、必要なら networks: { default: { driver: bridge } } を明示