Skip to content

Docker 网络 ​

1. 网络对象与驱动 ​

列出网络:

bash
docker network ls
docker network inspect bridge

常见驱动:

驱动范围用途
bridge单台 Linux Engine独立容器与 Compose 的默认选择
host宿主机网络命名空间极少数低开销或特殊网络程序
none无普通网络接口完全离线或自行配置网络
overlaySwarm 多节点Swarm 服务跨主机通信
macvlan二层网络容器像物理主机一样拥有 LAN 地址
ipvlan二/三层网络大规模或特定网络拓扑

本文重点介绍单机 Engine 的 user-defined bridge。

2. 默认 bridge 与自定义 bridge ​

自定义 bridge 提供更好的 DNS、隔离和生命周期管理:

bash
docker network create app-net

docker run -d --name db \
  --network app-net \
  alpine:3.23 sleep 300

docker run --rm --network app-net \
  busybox nslookup db

此处名为 db 的 Alpine 容器只用于 DNS 演示,不运行数据库,也无数据库初始化前置。先用 docker ps --filter name=db 核对它仍在运行;练习结束后 docker rm -f db 并在无引用时移除 app-net。各节命令是独立示例,第 3 节不要重复创建同名网络。

同一自定义网络中的容器可通过容器名或 network alias 解析。不要依赖动态容器 IP:

bash
docker network inspect app-net \
  --format '{{json .Containers}}'

默认 bridge 的旧式 --link 已不适合作为服务发现方案。

3. 创建带子网的网络 ​

bash
docker network create \
  --driver bridge \
  --subnet 172.30.10.0/24 \
  --gateway 172.30.10.1 \
  app-net

静态地址仅在明确需要时使用:

bash
docker run -d \
  --name legacy \
  --network app-net \
  --ip 172.30.10.20 \
  legacy-app:1.0

规划前核对:

bash
ip route
docker network ls
docker network inspect NETWORK

网段不能与宿主机 LAN、VPN、VPC、Kubernetes Pod/Service CIDR 冲突。

4. 连接多个网络 ​

bash
docker network create frontend
docker network create backend

docker run -d --name api --network frontend team-api:latest
docker network connect backend api

docker network inspect frontend
docker network inspect backend

断开:

bash
docker network disconnect frontend api

连接多个网络可以分隔入口与数据层,但不自动实现应用级授权。仍需认证、TLS 和最小端口暴露。

5. Network alias ​

bash
docker run -d \
  --name api-blue \
  --network app-net \
  --network-alias api \
  team-api:blue

同一 alias 可对应多个容器,DNS 可能返回多个地址;这不是具备健康检查、会话保持和高级负载均衡的完整服务发现系统。

6. 端口发布 ​

语法:

text
HOST_IP:HOST_PORT:CONTAINER_PORT[/PROTOCOL]

示例:

bash
# 仅宿主机可访问
docker run -d --name local-web \
  -p 127.0.0.1:8080:80 \
  nginx:alpine

# 所有 IPv4 地址可访问
docker run -d --name public-web \
  -p 0.0.0.0:8081:80 \
  nginx:alpine

# UDP
docker run -d --name dns \
  -p 127.0.0.1:5353:53/udp \
  dns-image:1.0

省略宿主机地址通常会绑定所有地址:

bash
docker run -p 8080:80 nginx

安全警告: 这可能使服务对办公网或公网可达。优先写明 127.0.0.1,需要外部访问时由反向代理、防火墙和安全组控制。

查看映射:

bash
docker port local-web
docker inspect local-web --format '{{json .NetworkSettings.Ports}}'
ss -lntup

随机宿主机端口:

bash
docker run -d -P --name random-web nginx:alpine
docker port random-web 80/tcp

7. EXPOSE 与 publish 的区别 ​

Dockerfile:

dockerfile
EXPOSE 8080

EXPOSE 是镜像元数据,说明应用预期监听端口;它不会自动开放宿主机端口。真正发布需要 docker run -p 或 Compose ports。

容器间在同一网络直接使用容器端口:

text
http://api:8080

不是宿主机发布端口。

8. 容器 DNS ​

自定义网络中的内置 DNS 通常在容器 /etc/resolv.conf 中体现:

bash
docker exec api cat /etc/resolv.conf
docker exec api getent hosts db

指定 DNS:

bash
docker run --rm \
  --dns 10.0.0.53 \
  --dns-search example.internal \
  alpine cat /etc/resolv.conf

daemon 全局 DNS 配置会影响新建容器。变更前评估 split DNS、VPN 和内部域名。

9. 从容器访问宿主机 ​

不要硬编码 bridge gateway。Linux Engine 可显式映射:

bash
docker run --rm \
  --add-host host.docker.internal:host-gateway \
  curlimages/curl \
  http://host.docker.internal:8080

Docker Desktop 通常提供 host.docker.internal。生产中更推荐通过稳定网络端点访问宿主服务。

10. 内部网络 ​

bash
docker network create --internal backend-only

内部网络限制外部连接路径,适合数据库或队列层。连接到多个网络的容器可能仍能转发流量,因此不要把它当作唯一安全边界。

11. Host 网络 ​

bash
docker run --rm --network host nginx:alpine

Host 模式共享宿主网络命名空间:

  • 不需要 -p,端口直接占用宿主机;
  • 隔离减弱;
  • 端口冲突直接发生;
  • 跨平台行为和支持范围不同。

仅在测量证明需要且安全评审通过时使用。

12. None 网络 ​

bash
docker run --rm --network none alpine ip addr

通常只有 loopback。适合纯计算任务或测试网络依赖,但挂载和其他权限仍需单独限制。

13. IPv6 ​

IPv6 需要 daemon、网络地址池、防火墙和上游路由共同配置。示例:

bash
docker network create \
  --ipv6 \
  --subnet fd00:30:10::/64 \
  dual-stack-net

检查:

bash
docker network inspect dual-stack-net
docker run --rm --network dual-stack-net alpine ip -6 addr

不要只为容器分配 IPv6 而遗漏入口防火墙、DNS AAAA、出站路由和监控。

14. Firewall ​

Docker 会创建 iptables/nftables 相关规则。重要原则:

  • 不要手工删除 Docker 自动维护的 chain。
  • 入口控制可放在云安全组、外部防火墙和 DOCKER-USER chain。
  • 发布端口可能绕过 ufw 的直观策略,应做真实连通性测试。
  • Engine 29 的 nftables 后端版本状态和限制应以当前官方文档为准。

查看现场:

bash
sudo iptables -S DOCKER-USER
sudo iptables -t nat -S DOCKER
sudo nft list ruleset

命令可能因所选后端而不同,不要同时用多个工具随意改规则。

15. Macvlan/IPvlan 注意 ​

Macvlan 可让容器直接出现在物理二层网络,但:

  • 交换机端口需允许多个 MAC;
  • 宿主机与 macvlan 容器默认可能不能直接通信;
  • 地址必须由 IPAM 严格规划;
  • 云平台可能禁止这种二层行为;
  • 容器暴露面更接近真实主机。
bash
docker network create -d macvlan \
  --subnet=192.0.2.0/24 \
  --gateway=192.0.2.1 \
  -o parent=eth0 macvlan-net

以上地址仅是文档示例网段,不可直接用于生产。

16. 网络排障流程 ​

16.1 确认应用监听 ​

bash
docker exec api ss -lntup
docker logs --tail 100 api

应用应监听 0.0.0.0 或容器接口,而不是只监听容器内 127.0.0.1。

16.2 确认网络连接与 DNS ​

bash
docker inspect api --format '{{json .NetworkSettings.Networks}}'
docker network inspect app-net
docker exec api getent hosts db

16.3 从同网络探测 ​

bash
docker run --rm --network app-net \
  curlimages/curl -fsS http://api:8080/healthz

使用临时调试容器前,确保镜像来源可信且环境允许拉取。

16.4 从宿主机探测 ​

bash
docker port api
curl -v http://127.0.0.1:8080/healthz
ss -lntp | grep ':8080'

16.5 从外部探测 ​

核对安全组、防火墙、反向代理、DNS 和路由。不要因本机 curl 成功就判断公网可用。

17. 常见故障 ​

现象常见原因首查
容器名无法解析不在同一自定义网络docker network inspect
Connection refused进程未监听或端口错误ss、日志
Timeout路由、防火墙、服务卡死ip route、规则、stats
宿主端口占用其他进程/容器已监听ss -lntp、docker ps
外部不可达、本机可达绑定了 127.0.0.1 或入口策略阻断docker port、安全组
VPN 开启后失联Docker 子网与 VPN 网段冲突路由表、地址池
DNS 间歇失败上游 DNS、搜索域或 MTUresolv.conf、daemon 日志

18. 删除网络 ​

bash
docker network rm unused-net
docker network prune

警告: prune 会删除所有未被容器使用的自定义网络。先执行 docker network ls 并确认自动化不会依赖预创建网络。

19. 官方参考 ​

继续阅读