要約:手っ取り早い解決策
お困りですか?まずはDockerサービスを再起動して、正常に動作するか確認してみましょう。この簡単な手順で、ハングしたネットワークインターフェースや古いルーティングテーブルが解消されることがよくあります:
sudo systemctl restart docker
それでも解決しない場合は、コンテナに特定のDNSサーバーの使用を強制することができます。これによりホストの設定を完全にバイパスし、問題が全体的なものかローカルなものかを判断するのに役立ちます:
docker run --dns 8.8.8.8 alpine ping -c 4 google.com
実際には何が起きているのか?
curl: (6) Could not resolve host というエラーが表示される場合、コンテナが虚空に向かって叫んでいるような状態です。ネットワーク接続はありますが、「google.com」を 142.250.190.46 のようなIPアドレスに変換するための電話帳(DNS)が見つかりません。この問題は通常、以下の3つの領域のいずれかに起因します:
- IP転送のブロック: Linuxカーネルが、仮想Dockerブリッジから物理ネットワークカードへのトラフィックの転送を拒否しています。
- DNSループバックの問題: Dockerがコンテナ内で
127.0.0.53(Ubuntuのローカルアドレス)を使用しようとしていますが、コンテナ内にはそのアドレスが存在しません。 - サブネットの衝突: DockerのデフォルトのIP範囲が、オフィスのWi-FiやVPNと競合しています。
ステップバイステップの解決策
1. IPv4転送を有効にする
IP転送は、コンテナという孤島とインターネットという本土を結ぶ架け橋のようなものだと考えてください。これがオフになっていると、コンテナ同士の通信は可能ですが、外部の世界には到達できません。多くのセキュリティが強化されたLinuxディストリビューションでは、デフォルトでこれが無効になっています。
まず、現在のステータスを確認します:
sysctl net.ipv4.ip_forward
出力が 0 の場合、転送は無効です。これを修正するには、root権限で /etc/sysctl.conf を開きます:
sudo nano /etc/sysctl.conf
net.ipv4.ip_forward=1 という行を探します。行頭の # を削除してコメントアウトを解除してください。その行がない場合は、ファイルの最後に追加します。保存して、すぐに変更を適用します:
sudo sysctl -p
変更を加えた後は、Dockerの再起動を忘れないでください。
2. Dockerに信頼できるDNSをハードコードする
Dockerは通常、ホストから /etc/resolv.conf をコピーします。しかし、Ubuntuのような最近のディストリビューションでは systemd-resolved が使用されており、これはローカルループバックIP(127.0.0.53)を指しています。コンテナはこのアドレスに到達できません。Dockerがこれを検知すると、デフォルトでGoogleの 8.8.8.8 を使用しますが、企業のファイアウォールで外部DNSがブロックされている場合、コンテナは通信相手を見失います。
デーモン設定を編集することで、すべてのコンテナに対してグローバルDNSを設定できます:
sudo nano /etc/docker/daemon.json
以下の行を挿入します。冗長性のために、CloudflareとGoogleを組み合わせて使用することをお勧めします:
{
"dns": ["1.1.1.1", "8.8.8.8"]
}
新しい設定を反映させるために、デーモンを再起動します:
sudo systemctl restart docker
3. ネットワークサブネットの競合を解決する
Dockerは通常、デフォルトブリッジとして 172.17.0.0/16 サブネットを確保します。オフィスのネットワークやVPNも 172.17.x.x を使用している場合、パケットが迷子になります。コンピュータは、トラフィックをコンテナに送るべきか、それとも会社のメールサーバーに送るべきか判断できなくなります。
ip addr show を使用してホストのIP範囲を確認してください。重複がある場合は、ToolCraftの IP Subnet Calculator を使用して、10.50.0.1/24 のような競合しない安全な範囲を見つけます。その後、daemon.json で "bip": "10.50.0.1/24" キーを使用して設定できます。
4. UFW (Uncomplicated Firewall) ルールの修正
Ubuntuを実行している場合、UFWがDockerの転送しようとしているトラフィックを黙って破棄している可能性があります。デフォルトでは、UFWの転送ポリシーが DROP に設定されていることが多く、これがコンテナのインターネットアクセスを即座に遮断します。
UFW設定ファイルを開きます:
sudo nano /etc/default/ufw
DEFAULT_FORWARD_POLICY="DROP" を ACCEPT に変更します。ルールを適用するためにファイアウォールをリロードします:
sudo ufw reload
検証:解決しましたか?
以下の2つのテストを実行して、障害がどこで発生しているかを正確に特定します。これにより、DNSの問題と一般的なルーティングの問題を切り分けることができます。
テスト 1: DNS解決
docker run --rm alpine nslookup google.com
出力にIPアドレスが表示されれば、DNSは正常に動作しています。
テスト 2: 生の接続性
docker run --rm alpine ping -c 4 1.1.1.1
1.1.1.1 にはpingが通るのに、上記の nslookup が失敗する場合、問題は100% DNSに関連しています。両方が失敗する場合は、ステップ1と4に戻って、IP転送とファイアウォールの設定を再確認してください。
参考文献
- Dockerドキュメント: Bridge network driver
- Ubuntu Wiki: Understanding systemd-resolved
- Docker Engine: Daemon config reference

