整理说明:本文属于“2025-2026 技术笔记整理”系列,于 2026 年 8 月集中整理并公开发布。
先分清主机入站与容器转发
在 Ubuntu 上把 UFW 设为默认拒绝入站,并不等于 Docker 发布的端口也会自动被拒绝。执行 docker run -p 8080:80 或在 Compose 中写入 ports 后,Docker 会为目标端口建立地址转换和转发规则。典型的 iptables 后端中,外部数据包经过 DNAT 后进入转发路径,而 UFW 常见的入站规则主要作用于主机的 INPUT 链。因此,ufw status 没有放行 8080,外部仍可能访问容器。
把暴露范围写进部署配置
最可靠的第一步不是补一条拦截规则,而是避免发布不需要的端口。应用与数据库可加入同一个 Docker 网络,通过服务名通信;Compose 的 expose 只声明容器网络中的端口,不会把端口发布到主机。只需要由本机反向代理访问的服务,应绑定回环地址:
services:
app:
ports:
- "127.0.0.1:8080:80"
db:
expose:
- "3306"
对公网服务只发布反向代理的 80 和 443;SSH、数据库、管理面板等端口按来源地址限制。未指定主机地址的 8080:80 通常会绑定所有主机地址,不能把“容器里只监听一个端口”理解为“只有本机能访问”。IPv4 与 IPv6 也要分别核对。
用三组视角核对实际边界
sudo ufw status numbered
docker ps --format 'table {{.Names}}\t{{.Ports}}'
sudo ss -lntup
sudo iptables -S DOCKER-USER
ufw status 展示主机策略,docker ps 展示发布映射,ss 展示主机监听;三者必须结合外部机器的连接测试。不要只在服务器本机执行 curl localhost,因为它无法证明公网边界是否正确。
确需过滤已发布端口时
使用 Docker iptables 后端时,可在 DOCKER-USER 链加入转发前置策略,或把等价规则纳入经过验证的 UFW 扩展配置。该链看到的目标通常已经完成 DNAT,匹配的是容器地址和容器端口;若要匹配发布前的原始目标,需要 conntrack 条件。规则还应明确公网接口、允许来源、已建立连接和 IPv6 行为,并配置持久化,不能只临时执行一次命令。
- 优先取消发布,或绑定
127.0.0.1。 - 只让反向代理进入应用网络,不发布数据库端口。
- 变更后从允许与不允许的外部来源各测试一次。
- 升级 Docker、防火墙后重新检查规则顺序与实际端口。
安全边界应由“监听地址、Docker 网络、转发规则、UFW 主机规则”共同定义。只依赖其中一层,最容易在重建容器或新增端口时产生意外暴露。