Docker Swarm中Stunnel加密Redis时连接被拒绝问题排查
问题分析与解决方案
从你的日志和配置细节来看,核心问题出在Redis服务器端的stunnel监听绑定地址上,导致Docker Swarm overlay网络的请求无法被正确接收。
具体原因
先看Redis服务器容器的netstat输出:
tcp 0 0 10.0.0.14:6379 0.0.0.0:* LISTEN 37/stunnel4
这里能看到stunnel只绑定了容器自身的私有IP(10.0.0.14),而不是容器的所有网络接口(0.0.0.0)。在Docker Swarm的overlay网络中,服务redis_master对应一个虚拟IP(VIP)(也就是你客户端日志里的10.0.0.5),当客户端通过服务名redis_master发起连接时,Swarm会先将请求路由到这个VIP,再转发到容器的私有IP。但由于stunnel只监听了容器自己的IP,VIP的请求无法被stunnel接收,最终导致连接被拒绝。
而你服务器端的stunnel配置里写的是:
accept = redis_master:6379
这会让stunnel尝试绑定到redis_master主机名解析到的IP——在容器内部,redis_master解析的是容器自身的私有IP,而不是Swarm的VIP,所以stunnel只会监听这个单一IP,无法接收来自overlay网络的其他请求。
修复步骤
- 修改Redis服务器端stunnel配置
将accept参数改为监听所有网络接口:
pid = /run/stunnel-redis.pid output = /tmp/stunnel.log [redis-server] cert = /etc/stunnel/redis-server.crt key = /etc/stunnel/redis-server.key accept = 0.0.0.0:6379 # 改为监听所有接口,接收任意来源的请求 connect = 127.0.0.1:6378
这样stunnel会监听容器的所有网络接口,包括overlay网络分配的IP,就能接收来自Swarm VIP的请求了。
- 重启Redis服务
更新配置后,重新部署你的redis_master服务:
docker stack deploy -c docker-stack.yml your-stack-name
- 验证修复效果
在PHP-FPM容器中再次执行:
redis-cli -p 8001 ping
应该能正常返回PONG。同时可以查看Redis服务器容器的netstat,确认stunnel现在监听的是0.0.0.0:6379:
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 37/stunnel4
额外注意事项
- 在Docker Swarm中,服务间通信依赖overlay网络,不需要将端口发布到主机(
ports参数),所以redis_master服务里的ports: - "6379"可以移除,避免不必要的端口暴露。 - 后续部署到不同主机时,只要overlay网络配置正常,修改后的stunnel配置依然能正常工作,因为它会监听容器的所有网络接口,接受来自任意overlay网络节点的请求。
内容的提问来源于stack exchange,提问作者mitchcodes
相关产品推荐
相关产品推荐

