Docker网络隔离需四层协同:命名空间提供基础隔离,自定义网络切断默认互通,DOCKER-USER链写防火墙规则,运行时约束限制能力。默认bridge仅具基础隔离,容器仍可IP互通,iptables规则易被覆盖,必须主动分网、精准控流、分层设防。

Docker 网络实现容器间安全隔离与防火墙限制,核心不靠“默认就安全”,而在于主动分网、精准控流、分层设防。默认 bridge 网络虽有基础命名空间隔离,但容器仍能通过 IP 互通,且 iptables 规则由 Docker 自动管理,用户规则易被覆盖——必须用对位置、选对层级、配对策略。
用自定义网络切断默认互通
默认 bridge 网络下,所有容器在同一个子网(如 172.17.0.0/16),仅靠端口不暴露并不等于隔离。真正阻断容器间通信,应弃用默认网,改用独立自定义桥接网络:
- 创建业务专属网络:
docker network create payment-net和docker network create user-net - 启动容器时显式指定网络:
docker run --network payment-net --name pg-db postgres,docker run --network user-net --name api-server nginx - 两个网络之间无路由、无 DNS 解析,
ping pg-db在 api-server 容器内直接失败,从网络层彻底隔开
注意:不要依赖 --icc=false(Docker 20.10+ 已默认关闭容器互通),它只影响默认 bridge;自定义网络天然不互通,更可靠、更清晰。
在 DOCKER-USER 链中写防火墙规则
Docker 启动时会自动操作 iptables 的 DOCKER 和 DOCKER-ISOLATION-STAGE-1 链,但这些链位于系统规则之后,用户无法直接插入。正确入口是 DOCKER-USER 链——它在 Docker 自有规则之前执行,且不会被 Docker daemon 覆盖。
- 禁止某类出口流量(如阻止所有容器连外网 MySQL):
iptables -A DOCKER-USER -m conntrack --ctorigdstport 3306 -j DROP - 限制入站:只允许宿主机访问容器的 80 端口,拒绝其他来源:
iptables -A DOCKER-USER -i docker0 ! -s 127.0.0.1 -p tcp --dport 80 -j DROP - 规则生效后需持久化(如 Ubuntu 上用
iptables-persistent保存,避免重启丢失)
配合运行时约束加固网络边界
网络隔离不能只靠“连不上”,还要控制“能做什么”:
- 禁用容器内网络特权:绝不使用
--privileged;如需操作 iptables,仅加最小能力:--cap-add=NET_ADMIN --cap-add=NET_RAW - 限制容器可绑定端口范围:用
--sysctl net.ipv4.ip_unprivileged_port_start=8080,让非 root 进程只能绑 ≥8080 的端口 - 暴露端口时绑定到本地回环:
-p 127.0.0.1:8000:80,避免监听 0.0.0.0,再统一由 Nginx 或 Traefik 做反向代理和 WAF 过滤 - 启动容器时关闭跨容器通信(即使在同一网络):
--network-alias替代隐式发现,或配合docker network connect --driver-opt com.docker.network.bridge.enable_ip_masquerade=false关闭 SNAT
验证隔离是否真正生效
配置完别假设它起作用,动手验证:
- 进容器执行
ip a确认 IP 属于预期子网(如 172.20.x.x),不是 172.17.x.x - 从 A 容器 ping B 容器名或 IP,确认超时;
telnet b-ip 3306应连接拒绝 - 在宿主机执行
iptables -t filter -L DOCKER-USER -n,确认你的规则已加载且顺序合理 - 尝试从容器内
curl http://host.docker.internal:3306(若启用),验证是否被规则拦截
网络隔离不是一劳永逸的设置,而是命名空间、自定义网络、iptables 链、运行时参数四层协同的结果。每层补一个缺口,整体才真正牢靠。


















