讲解
Docker 默认创建三个网络:bridge(默认桥接)、host(直接用宿主机网络栈,Linux 专属)、none(无网络)。不加 --network 的容器都进默认 bridge,彼此可以用容器 IP 通信——但 IP 会随重建变化,所以默认网络上按名字互访(内置 DNS)只对「用户自定义网络」生效。这是关键的实践分水岭:任何需要容器互访的场景,第一步都是 docker network create 建一个自定义网络。
自定义桥接网络上,容器用「容器名」或「网络别名」(--network-alias)互相解析。典型架构:web 容器和 db 容器加入同一个 app-net,web 用 mysql://db:3306 连数据库,db 完全不做 -p 映射——它不需要暴露给宿主机,攻击面瞬间缩小。端口映射只留给真正对外的入口。容器可以随时接入多个网络(docker network connect),也能断开(disconnect),这给「前后端分网」「管理网与业务网隔离」提供了原语。
排查网络问题的三板斧:docker network inspect 网络名 看哪些容器在网、各拿什么 IP;docker exec 进去 ping/wget 对端名字验证 DNS 与连通;docker logs 看应用日志确认连的地址对不对。九成「连不上」是:不在同一自定义网络、用了容器 IP 而非名字、或应用监听在 127.0.0.1。
示例
创建自定义网络,跑一个常驻容器进去:
docker network create ohmydocs-verify-net
docker run -d --name ohmydocs-verify-server --network ohmydocs-verify-net alpine:3.21 sleep 300
同网络的另一个容器用名字直接解析并 ping 通(自定义网络内置 DNS):
docker run --rm --network ohmydocs-verify-net alpine:3.21 ping -c 2 ohmydocs-verify-server
看网络的成员与 IP 分配:
docker network inspect ohmydocs-verify-net --format '{{range .Containers}}{{.Name}} = {{.IPv4Address}} {{end}}'
对照实验:默认 bridge 网络上的容器无法用名字解析对方(这也是要用自定义网络的原因)——本例预期解析失败:
docker run --rm alpine:3.21 sh -c "ping -c 1 -W 2 ohmydocs-verify-server" || echo "默认网络: 按名字解析失败, 符合预期"
清理容器和网络:
docker rm -f ohmydocs-verify-server && docker network rm ohmydocs-verify-net
常见坑
- 在默认 bridge 上按名字互访:解析不了,必须自建网络;Compose 会自动建网络,手写 run 命令时要自己建。
- 连数据库用 localhost:容器里的 localhost 是容器自己;要连另一个容器,用它的容器名/服务名。
- 重建后 IP 变了:别在配置里写死容器 IP,用名字;IP 会变是常态。
- 数据库也做 -p 映射:只对同机调试有必要;同网络内直连即可,少一个暴露面。
小结
自定义网络 = 内置 DNS + 按名互访 + 隔离边界;对外只暴露入口容器,内部服务零映射。单机网络至此够用,多机是 Swarm/Kubernetes 的话题。下一章开始自己造镜像:Dockerfile。