Ubuntu 22.04:docker:无法从外部访问容器

Ubuntu 22.04:docker:无法从外部访问容器

安装有现成的 Ubuntu 22.04,并按照以下说明安装 docker这本书

我还使用 docker-compose 启动了三个容器,它们使用起来很好docker ps

CONTAINER ID   IMAGE                             COMMAND                  CREATED          STATUS                   PORTS                                                                                  NAMES
60cf25f59a92   jc21/nginx-proxy-manager:latest   "/init"                  48 minutes ago   Up 8 minutes             0.0.0.0:80-81->80-81/tcp, :::80-81->80-81/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   infra_nginx_proxy_1
f8081b137abf   graylog/graylog:4.2               "tini -- /docker-ent…"   55 minutes ago   Up 8 minutes (healthy)   0.0.0.0:1514->1514/tcp, :::1514->1514/tcp, 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp   infra_graylog_1
d3fef3332752   elasticsearch:7.9.3               "/tini -- /usr/local…"   55 minutes ago   Up 8 minutes             9200/tcp, 9300/tcp                                                                     infra_elasticsearch_1
6b7920e89790   mongo:4.4.9                       "docker-entrypoint.s…"   56 minutes ago   Up 8 minutes             27017/tcp                                                                              infra_mongo_db_1

现在,当尝试卷曲其中一个局部时,一切都很好

root$: curl http://localhost:81

<!doctype html><html lang="en" dir="ltr"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1">...

但是相同的 curl(当然是针对公共 IP)以超时结束。

在 docker 主机上执行 tcpdump 可以发现这一点,流量正在到达

root$: tcpdump port 81
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
19:53:34.520888 IP 10.0.1.27.51942 > docker-infrastruktur.81: Flags [S], seq 1942358053, win 64240, options [mss 1460,sackOK,TS val 1217328475 ecr 0,nop,wscale 7], length 0
19:53:35.535503 IP 10.0.1.27.51942 > docker-infrastruktur.81: Flags [S], seq 1942358053, win 64240, options [mss 1460,sackOK,TS val 1217329490 ecr 0,nop,wscale 7], length 0
19:53:37.551436 IP 10.0.1.27.51942 > docker-infrastruktur.81: Flags [S], seq 1942358053, win 64240, options [mss 1460,sackOK,TS val 1217331506 ecr 0,nop,wscale 7], length 0
19:53:41.775510 IP 10.0.1.27.51942 > docker-infrastruktur.81: Flags [S], seq 1942358053, win 64240, options [mss 1460,sackOK,TS val 1217335730 ecr 0,nop,wscale 7], length 0

iptables-所有docker生成-看起来像这样

sudo iptables --list

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy DROP)
target     prot opt source               destination         
DOCKER-USER  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain DOCKER (2 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             172.18.0.2           tcp dpt:https
ACCEPT     tcp  --  anywhere             172.18.0.2           tcp dpt:81
ACCEPT     tcp  --  anywhere             172.18.0.2           tcp dpt:http
ACCEPT     tcp  --  anywhere             172.18.0.5           tcp dpt:9000
ACCEPT     tcp  --  anywhere             172.18.0.5           tcp dpt:1514

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination         
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            

甚至nmap表明所有的门都是敞开的

root$: sudo nmap localhost

Starting Nmap 7.80 ( https://nmap.org ) at 2022-08-12 19:56 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000013s latency).
Not shown: 995 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
81/tcp   open  hosts2-ns
443/tcp  open  https
9000/tcp open  cslistener

有趣的是,当启动本地 Web 服务器时,例如,python3 -m http.server 81它会启动(在关闭容器之后),并且可以访问。因此,我可以确定外部防火墙或甚至主机操作系统存在问题...

请提供帮助和建议。

答案1

我遇到了同样的问题(尽管我的 22.04 是从 20.04 升级而来的)。症状完全相同,所以我在这里分享解决方案,也许它对某些人有帮助。我尝试按照这里的建议重新安装 docker,但没有成功。重新安装服务器不是一个选择。

最后,这个问题与iptables-nft 和 snap(还报告给docker-snap):

如果软件在配置的符号链接之外操纵防火墙(或使用 iptables-legacy/iptables 1.6,同时使用 nftables),则如果它们不知道 xtables/netfilter 不兼容,则可能会引发问题。例如,这可能会发生在发布自己的 iptables 或 nftables 的 snap 中,并且无条件地使用它,而不考虑系统上的现有规则。[...] 稳定频道中自 20.10.12 起的“docker”snap 已知无条件使用 xtables。在提交此文件时,它没有办法调整使用 netfilter,因此如果使用 docker snap,您可能必须更新系统以使用 iptables-legacy(在 Debian/Ubuntu 上,请参阅上面的 update-alternatives)。

我发现/etc/alternatives/iptables指向/usr/sbin/iptables-nft,但我也有iptables-legacy规则。请参阅:

$ sudo iptables -S
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
...
$ sudo iptables-legacy -S
-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
...

发现这个问题后,解决方案很简单:

sudo iptables-legacy -P FORWARD ACCEPT

答案2

无需重新安装整个系统。问题在于安装程序提供的 docker 的“snap”版本。如果您之后通过 apt 安装 docker,则最终会同时拥有两个二进制文件。只需删除 snap

sudo snap remove docker

并从官方 docker 存储库重新安装

sudo apt-get install --reinstall docker-ce docker-ce-cli containerd.io docker-compose-plugin

查看:https://docs.docker.com/engine/install/ubuntu/

答案3

经过进一步分析,我们发现了一个原因或促成因素:在安装操作系统时,还选择安装 docker。

之后我们按照安装指南进行操作(https://docs.docker.com/engine/install/ubuntu/)并删除所有“旧”版本

sudo apt-get remove docker docker-engine docker.io containerd runc

然后我们从 docker apt 源安装。

我们全新安装了操作系统,这次没有安装 docker,安装 docker 后一切正常。

答案4

结论:通过 SNAP 安装 Docker 时,您会遇到几个问题,这些问题会导致 Docker 无法开箱即用(自 22.04 起)。这些问题包括对原始套接字文件的权限不当,以及无法访问暴露的 Docker 端口。

解决方案:第一个命令更新防火墙,第二个命令用于增加套接字描述符上的权限。

sudo iptables-legacy -P FORWARD ACCEPT
sudo chmod 666 /var/run/docker.sock

相关内容