Docker 容器“无法联网”经常不是一个问题,而是三类问题混在一起:
- 容器访问不了公网 IP。
- 容器能访问 IP,但解析不了域名。
- 容器之间不能用服务名互相访问。
这三种现象的排查方向完全不同。很多人看到 Temporary failure resolving 就去改宿主机 DNS,看到容器互相 ping 不通就去改 Nginx,最后越改越乱。Docker 网络要先分清:容器自己的 DNS、Docker bridge 网络、宿主机转发规则、防火墙和 Compose 网络分别处在哪一层。
这篇按 VPS 上最常见的 Docker 网络故障来排查:从容器内测试开始,再看 127.0.0.11、默认 bridge 和自定义 bridge、docker network inspect、daemon.json DNS、防火墙和 systemd-resolved。
进入容器:
docker exec -it app sh
如果容器没有 sh,换成:
docker exec -it app bash
先测公网 IP:
ping -c 3 1.1.1.1
再测域名:
ping -c 3 google.com
如果 IP 能通、域名不通,优先查 DNS。
如果 IP 也不通,优先查 Docker 网络、NAT、转发和防火墙。
如果公网能通,但容器之间不能通过服务名访问,重点查 Docker 网络类型:你可能还在用默认 bridge,而不是用户自定义 bridge 或 Compose 默认网络。
在容器里执行:
cat /etc/resolv.conf
如果容器在用户自定义 bridge 或 Docker Compose 网络里,常见结果是:
nameserver 127.0.0.11
options ndots:0
127.0.0.11 是 Docker 的内置 DNS。它负责两件事:
- 给容器转发外部 DNS 查询。
- 在用户自定义网络里解析容器名和服务名。
如果你看到的不是 127.0.0.11,而是宿主机上的某个本地地址,比如 127.0.0.53,要警惕 systemd-resolved 相关问题。容器里的 127.0.0.53 指向的是容器自己,不是宿主机的 resolved 服务,通常会解析失败。
这是 Docker 网络里最容易被忽略的一点。
直接这样启动的容器:
docker run -d --name app nginx
默认进入 Docker 的默认 bridge 网络。默认 bridge 上,容器之间通常不能自动用容器名解析。
更推荐创建自定义网络:
docker network create app-net
然后启动容器:
docker run -d --name redis --network app-net redis:7
docker run -d --name app --network app-net nginx
在同一个自定义 bridge 网络里,容器可以用名字访问:
redis:6379
Docker Compose 默认也会为项目创建一个自定义网络,所以 Compose 里的服务名通常能互相解析。比如:
services:
app:
image: my-app
depends_on:
- redis
redis:
image: redis:7
app 里访问 Redis 应该写:
redis:6379
不是 127.0.0.1:6379。容器里的 127.0.0.1 指的是容器自己,不是宿主机,也不是另一个容器。
不要只看 docker ps。网络问题要看 network inspect。
列出网络:
docker network ls
查看某个网络:
docker network inspect app-net
重点看:
- 容器是否真的在同一个网络里。
- 容器名和别名是否存在。
- Subnet / Gateway 是否和宿主机网络冲突。
- 是否意外用了
host、none或旧的默认bridge。
如果容器没有加入正确网络,可以临时连接:
docker network connect app-net app
长期配置应该写回 Compose 文件,而不是靠手工 connect 维持。
先在容器里装一个调试工具。Debian/Ubuntu 容器:
apt update
apt install -y dnsutils iputils-ping curl
Alpine 容器:
apk add --no-cache bind-tools iputils curl
如果 apt update 本身就因为 DNS 失败跑不起来,可以临时启动一个测试容器:
docker run --rm -it --dns 1.1.1.1 debian:12 bash
测试解析:
nslookup debian.org
nslookup debian.org 1.1.1.1
如果指定 1.1.1.1 能解析,而默认解析失败,说明 Docker 默认 DNS 链路有问题。
可以在 /etc/docker/daemon.json 里指定 DNS:
{
"dns": ["1.1.1.1", "8.8.8.8"]
}
然后重启 Docker:
sudo systemctl restart docker
注意:重启 Docker 会影响正在运行的容器。生产机器上先评估影响,必要时安排维护窗口。
Ubuntu 上常见:宿主机 /etc/resolv.conf 指向:
nameserver 127.0.0.53
这是宿主机本地的 systemd-resolved stub resolver。Docker 通常会处理这种情况,但在某些镜像、老版本 Docker、手动改过 resolv.conf 或 daemon 配置后,容器可能拿到不适合自己的 DNS。
宿主机上先看:
resolvectl status
ls -l /etc/resolv.conf
cat /etc/resolv.conf
如果你之前为了修 DNS 手动改过 /etc/resolv.conf,要先确认没有把宿主机 DNS 配坏。宿主机 DNS 解析本身有问题时,先处理:VPS DNS 解析失败怎么办。
如果容器里连公网 IP 都不通,查宿主机是否开启 IPv4 转发:
sysctl net.ipv4.ip_forward
正常应该是:
net.ipv4.ip_forward = 1
Docker 通常会自动设置它。如果是 0,可以临时启用:
sudo sysctl -w net.ipv4.ip_forward=1
再看 Docker 是否创建了 NAT 规则。iptables 系统:
sudo iptables -t nat -S | grep DOCKER
nftables 系统:
sudo nft list ruleset | grep -i docker
如果你装过 UFW、firewalld、nftables 规则脚本,或者手动清理过 iptables,可能把 Docker 的转发和 NAT 规则破坏了。
这类情况常见现象是:
- 容器能启动。
- 端口映射看起来存在。
- 容器访问外网失败。
- 重启 Docker 后短暂恢复,之后又被防火墙脚本覆盖。
Ubuntu VPS 上很多人用 UFW 管端口,但 Docker 会直接操作 iptables/nftables。结果是:你以为 UFW 拦住了某个端口,Docker 映射端口却仍然对外开放;或者你改了 UFW 默认转发策略,容器出站失败。
先看 UFW 状态:
sudo ufw status verbose
再看默认转发策略:
grep DEFAULT_FORWARD_POLICY /etc/default/ufw
如果是:
DEFAULT_FORWARD_POLICY="DROP"
可能会影响容器转发。很多教程会让你改成 ACCEPT,但这会扩大转发面,生产环境要结合实际规则评估。
更稳的做法是:
- 不要随便 flush Docker 创建的规则。
- 防火墙脚本重载后检查容器出站。
- 对外暴露端口用反向代理统一入口,而不是到处
-p 0.0.0.0:xxxx:xxxx。
如果你的问题是“服务启动了但外网访问不了”,可以对照:VPS 服务启动了但外网访问不了:端口、防火墙、安全组、监听地址。
Compose 里服务名解析失败,通常不是 DNS 服务器坏了,而是配置写法不对。
常见错误一:写 localhost。
REDIS_HOST=localhost
在容器里,localhost 是当前容器。应该写服务名:
REDIS_HOST=redis
常见错误二:两个服务不在同一个网络。
services:
app:
networks:
- frontend
redis:
networks:
- backend
这样 app 默认解析不到 redis。需要让它们共享一个网络,或显式规划网络边界。
常见错误三:把 container_name 当成扩展能力。
container_name 不是必须的,很多时候反而会让多副本、项目隔离和命名冲突变麻烦。Compose 默认服务名已经足够作为内部 DNS 名。
遇到容器无法联网或无法解析域名,按这个顺序查:
- 容器里先测 IP:
ping 1.1.1.1。 - 再测域名:
ping debian.org或nslookup debian.org。 - 查看容器
/etc/resolv.conf,确认是否使用127.0.0.11。 docker network ls和docker network inspect看容器是否在正确网络。- 如果容器互访失败,优先改成自定义 bridge 或 Compose 网络。
- 如果 DNS 失败,临时用
--dns 1.1.1.1验证是不是 DNS 链路问题。 - 必要时配置
/etc/docker/daemon.json的dns。 - 检查宿主机
resolvectl status和/etc/resolv.conf。 - IP 也不通时查
net.ipv4.ip_forward和 Docker NAT 规则。 - 检查 UFW/firewalld/nftables 是否破坏 Docker 转发。
VPS 上 Docker 容器无法联网,不要只盯着一个报错。先分清是公网 IP 不通、DNS 不通,还是容器之间服务名解析失败。
如果是容器互访,优先确认是否在同一个自定义 bridge 或 Compose 网络;如果是外部域名解析,重点看 127.0.0.11、宿主机 DNS 和 daemon.json;如果 IP 都不通,再查转发、NAT 和防火墙。把这几层拆开后,Docker 网络问题就不会再像黑盒。
