Ubuntu ホスト上の docker で実行されている Web アプリがいくつかあります。各アプリは異なるポートでリッスンしています。docker ネットワーク内の任意のコンテナー内では、サービスに接続してデータを受信できますが、ホストからの要求を実行すると、正常に接続できますが、データは受信されません。コンテナーの外部からサービスに接続したときに、サービスがデータを返さないのはなぜですか?
次を実行すると、Docker は「PORTS」の下にこれを報告しますdocker ps
:
0.0.0.0:8080->8080/tcp, :::8080->8080/tcp
そして、netstat はサーバーがそのポートをリッスンしていることを報告します。
$ netstat -anp | grep 8080
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN -
tcp6 0 0 :::8080 :::* LISTEN -
しかし、ブラウザで localhost:8080 にアクセスすると (Firefox と Chrome の両方を試しました)、ブラウザはハングし、接続されているがデータが送信されていないように見えます。同様に、curl は永久にハングします。
$ curl -vvv localhost:8080
* Uses proxy env variable no_proxy == 'localhost,127.0.0.1,::1'
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
^C
また、telnet で接続してみましたが、結果は同じでした。ホスト上で直接、簡単な http サーバーを実行してみましたが、問題なく動作しました。
python3 -m http.server 8000
$ curl -vvv localhost:8000
* Uses proxy env variable no_proxy == 'localhost,127.0.0.0/8,::1'
* Trying 127.0.0.1:8000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.8.13
< Date: Fri, 09 Dec 2022 12:36:03 GMT
< Content-type: text/html; charset=utf-8
< Content-Length: 16768
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
...
また、docker コンテナの IP: (172.17.0.3:8080) に接続してみましたが、結果は同じでした。
ただし、コンテナーの 1 つ内で curl を実行しようとすると、どのコンテナーでも http エンドポイントにアクセスできます。
これらすべてから、ホスト上の docker ネットワーク (docker ブリッジ?) に問題があると考えられます。
私は docker compose を使用しています。Docker inspect は次のようなレポートを出力します (一部)。
"HostConfig": {
"Binds": [],
...
"NetworkMode": "docker-compose-example_default",
"PortBindings": {
"8080/tcp": [
{
"HostIp": "",
"HostPort": "8080"
}
]
},
...
"NetworkSettings": {
"Bridge": "",
"SandboxID": "1b53a5b6580187b714c6d7d0c9f81a015d585cd0bb0d62da579a4fe7514d47ea",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"8080/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "8080"
},
{
"HostIp": "::",
"HostPort": "8080"
}
]
},
"SandboxKey": "/var/run/docker/netns/1b53a5b65801",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"MacAddress": "",
"Networks": {
"docker-compose-example_default": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"dc0813038a3b",
"adminer"
],
"NetworkID": "65c6700f5445a6ce0f98a0a4e14e3e10577f40706411f639a4f9da5b1cfdd52e",
"EndpointID": "0f42ae8ce893fb4f33168c31df0d5de38d2e8ca67521802ba76589a8a0cb1bea",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
}
}
}
要約: コンテナ内ではこれらのサービスに接続できますが、すべてのレポートによるとサーバーが接続をリッスンしているにもかかわらず、ホストからは接続できません。
ホストから docker 内で実行されているサービスに接続するには、何をする必要がありますか?
答え1
回避策は見つかりましたが、解決策は見つかりませんでした。この問題は、VPN に接続しているときのみ発生することがわかりました。どうやら、これはよくある苦情のようです。切断すると、接続は期待どおりに機能します。
回避策としては、VPN をオフにして、Docker コンテナを再起動することです。ちなみに、これは必ずしも機能するとは限りません。特に、VPN をオンにして実行し、VPN をオフにしてから再試行した場合はそうです。この場合、docker-compose ネットワークの CIDR を変更すると、問題が解決することがわかりました。同じ問題に遭遇している方のお役に立てれば幸いです。
VPN をオンにした状態で動作させる方法についてはまだ結論が出ていませんが、これまでのところ、どのアプローチも (「tombstone」Docker ブリッジの作成を含め) うまくいきませんでした。