centos7 docker中的 redis不能访问
CentOS Docker Redis 端口映射外部无法访问问题排查与解决
1. 问题背景
在 CentOS 虚拟机中通过 Docker 启动 Redis 容器,并进行端口映射:
docker run -d \
--name redis \
-p 6379:6379 \
redis/redis-stack:latest
虚拟机 IP 为:
192.168.1.11
Windows 宿主机 IP 为:
192.168.1.5
目标是让 Windows 宿主机访问虚拟机中的 Redis:
192.168.1.11:6379
2. 问题现象
2.1 容器运行正常
执行:
docker ps
可以看到 Redis 容器正常运行,且 6379 端口已映射。
2.2 虚拟机本机访问正常
在 CentOS 虚拟机中执行:
redis-cli -h 127.0.0.1 -p 6379
redis-cli -h 192.168.1.11 -p 6379
可以正常连接。
说明:
- Redis 服务正常
- Docker 端口映射对本机访问有效
2.3 Windows 宿主机访问失败
在 Windows 上执行:
Test-NetConnection 192.168.1.11 -Port 6379
测试失败,连接超时。
说明:
- 外部无法访问 Redis 的映射端口
3. 排查过程
3.1 检查 Docker 端口映射是否正常
执行:
docker port redis
docker inspect redis
确认 Redis 容器端口映射存在,6379 已映射到宿主机。
另外确认容器 IP:
docker inspect -f '{{ .NetworkSettings.IPAddress }}' redis
输出:
172.17.0.2
说明容器实际运行在 Docker 默认网桥网络中。
3.2 抓取宿主机物理网卡流量
在 CentOS 上执行:
tcpdump -nn -i ens33 host 192.168.1.5 and port 6379
抓包结果显示 Windows 发来的 SYN 报文可以到达宿主机网卡。
说明:
- Windows 到 CentOS 宿主机网络是通的
- VMware 网络本身没有问题
3.3 抓取 docker0 网桥流量
执行:
tcpdump -nn -i docker0 port 6379
没有看到任何流量。
说明:
- 数据包到达了宿主机
- 但没有继续进入 Docker 网桥
- 问题在宿主机内核转发、NAT 或防火墙链路
3.4 检查 NAT 规则是否命中
执行:
iptables -t nat -L -n -v | grep 6379
输出类似:
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:6379
65 3420 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:6379 to:172.17.0.2:6379
说明:
- Docker 的 DNAT 规则已经生效
- 外部访问 6379 时,目标地址已经转换为容器地址
172.17.0.2:6379
3.5 检查转发链
执行:
iptables -L FORWARD -n -v
iptables -S DOCKER-USER
iptables -S DOCKER
关键输出如下:
Chain FORWARD (policy DROP)
...
ACCEPT all -- * docker0 ctstate RELATED,ESTABLISHED
DOCKER all -- * docker0
ACCEPT all -- docker0 !docker0
以及:
-A DOCKER-USER -j RETURN
和:
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 6379 -j ACCEPT
说明:
DOCKER-USER没有额外拦截- Docker 的 FORWARD 规则正常
- 6379 到容器的 ACCEPT 规则存在
因此,问题不在 iptables 放行规则本身。
3.6 检查内核 IP 转发开关
执行:
sysctl net.ipv4.ip_forward
输出:
net.ipv4.ip_forward = 0
这就是根因。
4. 根因分析
Linux 内核参数:
net.ipv4.ip_forward
控制系统是否允许 IPv4 转发。
当其值为 0 时:
- 主机只处理发给自己的数据包
- 不会将收到的数据包转发到其他网络接口
- Docker 即使完成了 DNAT,也无法把流量继续转发到
docker0和容器网络
因此出现如下现象:
ens33能看到外部 SYNnat PREROUTING已命中 DNATdocker0上看不到流量- 外部访问 Redis 超时
5. 解决方案
5.1 临时生效
执行:
sysctl -w net.ipv4.ip_forward=1
验证:
sysctl net.ipv4.ip_forward
期望输出:
net.ipv4.ip_forward = 1
之后重新从 Windows 测试:
Test-NetConnection 192.168.1.11 -Port 6379
通常即可恢复正常。
6. 建议同时调整的参数
为了避免 Docker、多网桥、虚拟化场景下出现反向路径校验导致的丢包,建议同时设置:
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
参数说明:
-
net.ipv4.ip_forward = 1
开启 IPv4 转发,允许宿主机把外部流量转发到容器网络 -
net.ipv4.conf.all.rp_filter = 0
关闭所有网卡的反向路径过滤,避免复杂网络场景下误丢包 -
net.ipv4.conf.default.rp_filter = 0
关闭新建网卡的默认反向路径过滤,避免后续 Docker bridge 默认启用严格检查
7. 持久化配置
7.1 推荐方式:写入 /etc/sysctl.d/
创建配置文件:
cat > /etc/sysctl.d/99-docker-network.conf <<'EOF'
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
EOF
加载配置:
sysctl --system
7.2 也可写入 /etc/sysctl.conf
编辑:
vi /etc/sysctl.conf
加入:
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
执行:
sysctl -p
8. 验证配置
执行:
sysctl net.ipv4.ip_forward
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.default.rp_filter
期望输出:
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
9. 最终结论
本次问题的根因不是:
- Redis 服务异常
- Docker 端口映射错误
- Windows 防火墙问题
- VMware 网络不通
真正根因是:
net.ipv4.ip_forward = 0
导致外部访问到达 CentOS 宿主机后,无法继续转发到 Docker 容器网络。
将其修改为:
net.ipv4.ip_forward = 1
后,外部访问恢复正常。
10. 可直接执行的命令
10.1 临时生效
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.conf.all.rp_filter=0
sysctl -w net.ipv4.conf.default.rp_filter=0
10.2 永久生效
cat > /etc/sysctl.d/99-docker-network.conf <<'EOF'
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
EOF
sysctl --system
10.3 验证
sysctl net.ipv4.ip_forward
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.default.rp_filter
11. 故障定位关键证据汇总
11.1 容器 IP
docker inspect -f '{{ .NetworkSettings.IPAddress }}' redis
输出:
172.17.0.2
11.2 NAT 命中
iptables -t nat -L -n -v | grep 6379
输出:
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:6379
65 3420 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:6379 to:172.17.0.2:6379
11.3 内核转发关闭
sysctl net.ipv4.ip_forward
输出:
net.ipv4.ip_forward = 0
12. 一句话总结
外部流量已经到达宿主机并完成 DNAT,但由于 CentOS 未开启 net.ipv4.ip_forward,数据包无法继续转发到 Docker 容器,导致 Redis 映射端口外部访问失败。

浙公网安备 33010602011771号