Docker网络防火墙核心在于正确使用DOCKER-USER链和自定义网络:用DOCKER-USER链添加用户规则(如限制3306、控制80端口访问源),创建--internal网络实现容器间隔离,配置firewalld/UFW信任docker0或显式放行端口,并通过127.0.0.1绑定+反向代理增强安全。
docker host 网络本身不提供防火墙能力,真正起作用的是宿主机的 iptables(或 nftables)规则。关键在于:docker 自动管理的规则链(如 docker、docker-isolation)位于系统防火墙之后,用户若直接改 input/forward 链,容易被 docker 覆盖或与 firewalld 冲突。必须用对位置、选对链、配对策略。
用 DOCKER-USER 链做第一道可控防线
这是 Docker 明确保留给用户写规则的位置,它在所有 Docker 自有规则之前执行,且不会被 dockerd 重启覆盖。
- 禁止容器访问外部 MySQL(3306):
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 - 限制某容器网段(如 172.20.0.0/16)对外发起 SSH 连接:
iptables -A DOCKER-USER -s 172.20.0.0/16 -p tcp --dport 22 -j REJECT
配合自定义网络切断默认互通
默认 bridge 网络下,所有容器共享子网(如 172.17.0.0/16),仅靠端口不暴露 ≠ 隔离。必须显式划分业务网络。
- 创建内部隔离网:
docker network create --internal payment-net(禁外网) - 创建带 DNS 的业务网:
docker network create user-api-net - 启动容器时绑定网络:
docker run --network payment-net postgres和docker run --network user-api-net nginx—— 两网之间无路由、无 DNS 解析,ping直接不通
处理 firewalld 或 UFW 的兼容问题
firewalld 启动时会清空 iptables 规则,导致 Docker 网络中断;UFW 默认策略也可能拦截容器映射端口。
- CentOS/RHEL 上:停用 firewalld 或配置其信任 docker0 接口:
firewall-cmd --permanent --zone=trusted --add-interface=docker0,再重载 - Ubuntu 上用 UFW:设默认策略为 deny,再显式放行映射端口,例如:
ufw allow 8080/tcp;避免用ufw enable后再跑 Docker,否则需手动加ufw allow from 172.17.0.0/16 - 规则持久化:Ubuntu 用
iptables-persistent保存 DOCKER-USER 规则,防止重启丢失
暴露端口时绑定到本地回环再统一代理
别让容器监听 0.0.0.0,而是限定只响应宿主机自身请求,再由 Nginx/Traefik 做入口过滤和 WAF。
- 运行容器时指定绑定地址:
docker run -p 127.0.0.1:8000:80 nginx - 这样外部无法直连 8000,只能走反向代理层,便于集中做 IP 白名单、速率限制、SQL 注入检测
- 配合 sysctl 限制非 root 绑定端口:
--sysctl net.ipv4.ip_unprivileged_port_start=8080,降低提权风险


















