Docker容器端口问题:Gunicorn绕过Nginx公网可访问求助
解决Docker Swarm中Gunicorn服务被公网直接访问的问题
你遇到的核心问题是Docker的端口映射默认会绑定宿主机的所有网络接口(0.0.0.0),这会直接添加iptables规则放行该端口,完全绕过ufw的配置。所以即使你限制了ufw,公网依然能访问8000端口。下面给你几个可行的解决方案,按推荐程度排序:
方案1:移除端口映射,通过Docker内部网络让Nginx访问Gunicorn(最安全)
这个方案能让Gunicorn完全隐藏在Docker内部网络,只对Nginx开放,彻底杜绝公网访问的可能:
- 修改
docker-compose.yml,删除ports: - "8000:8000"这一行。此时Gunicorn的8000端口仅在webnet网络内部可见,外部(包括宿主机默认状态)无法直接访问。 - 将宿主机的Nginx接入Docker的
webnet网络:# 先查看你的Swarm栈对应的网络名称(一般是「栈名_webnet」,比如栈叫myapp就是myapp_webnet) docker network ls # 将宿主机加入该网络 docker network connect your_stack_webnet $(hostname) - 修改Nginx的upstream配置,把
localhost:8000改成Gunicorn的服务名gunicorn:8000(Docker内部网络支持通过服务名直接解析):upstream gunicorn { server gunicorn:8000; } - 重启Nginx并重新部署栈:
systemctl reload nginx docker stack deploy -c docker-compose.yml your_stack_name
方案2:限制端口映射到宿主机回环地址(快速修复)
如果不想调整网络结构,只想快速阻止公网访问,可以修改端口映射仅绑定宿主机的127.0.0.1:
- 更新
docker-compose.yml的ports配置:ports: - "127.0.0.1:8000:8000" - 清理旧栈并重新部署(避免缓存导致配置不生效):
docker stack rm your_stack_name docker system prune -f docker stack deploy -c docker-compose.yml your_stack_name - 验证端口绑定状态:
你应该看到输出显示netstat -tulpn | grep 8000127.0.0.1:8000,而非0.0.0.0:8000,此时公网无法访问该端口,宿主机的Nginx仍能通过localhost:8000连接Gunicorn。
方案3:全局配置Docker默认绑定回环地址
如果希望所有Docker容器的端口映射都默认限制在宿主机内部,可以修改Docker的全局配置:
- 编辑(或创建)
/etc/docker/daemon.json:{ "ip": "127.0.0.1" } - 重启Docker服务:
systemctl restart docker - 重新部署你的Swarm栈,此后所有端口映射都会自动绑定到127.0.0.1,无需单独配置。
额外注意点
- Swarm部署时,避免使用
--publish-all参数,防止意外暴露容器端口; - 检查ufw规则,确保没有手动放行8000端口,同时无需删除Docker自动添加的iptables规则(我们已经从端口绑定层面限制了访问)。
内容的提问来源于stack exchange,提问作者vincent-lg
相关产品推荐
相关产品推荐

