docker networking: браузер и curl зависают при подключении к серверу на локальном хосте

docker networking: браузер и curl зависают при подключении к серверу на локальном хосте

У меня есть несколько веб-приложений, работающих в docker на хосте ubuntu. Каждое приложение прослушивает отдельный порт. Находясь внутри любого контейнера в сети 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">
...

Я также попробовал подключиться к IP-адресу контейнера Docker: (172.17.0.3:8080) с тем же результатом.

Однако когда я пытаюсь запустить curl внутри одного из контейнеров, я могу достичь конечных точек http в любом контейнере.

Все это наводит меня на мысль, что на моем хосте возникла проблема с сетевым подключением Docker (Docker Bridge?).

Я использую 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. В этом случае я обнаружил, что изменение CIDR в сети docker-compose позволило мне заставить все работать. Надеюсь, это поможет тем, кто сталкивается с той же проблемой.

Пока еще не решено, как заставить все работать при включенном VPN, ни один из подходов (включая создание моста Docker «надгробного камня») мне не помог.

Связанный контент