You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

配置Docker daemon为--iptables=true和--userland-proxy=false后,如何实现容器通过主机转发端口互通?

解决容器通过主机转发端口互访的问题(禁用userland-proxy后)

刚好碰到过类似的场景,当你把Docker daemon配置成--iptables=true--userland-proxy=false后,容器没法通过主机IP访问本地转发端口确实是Docker的默认行为——因为禁用userland-proxy后,Docker依赖iptables做端口转发,但默认的FORWARD链规则会阻止docker0接口上的回环流量(容器→主机→容器的路径)。下面给你几个不需要每次启动容器手动改iptables的持久化方案:

方案1:添加持久化的iptables FORWARD规则

这是最直接的解决办法,我们需要允许docker0接口内部的双向转发流量:

  1. 临时测试(重启后失效)
    先执行这条命令验证是否解决问题:

    iptables -A FORWARD -i docker0 -o docker0 -j ACCEPT
    

    测试容器能否通过主机IP访问对方的转发端口,如果可行,再做持久化。

  2. 持久化规则(CentOS/RHEL系)
    把规则保存到iptables配置文件:

    iptables-save > /etc/sysconfig/iptables
    

    或者创建自定义规则文件,通过iptables-restore加载(比如在/etc/rc.d/rc.local中添加加载命令)。

  3. 持久化规则(Debian/Ubuntu系)
    安装netfilter-persistent工具:

    apt-get install netfilter-persistent
    netfilter-persistent save
    

    这样规则会在系统重启后自动加载。

方案2:通过systemd服务自动添加规则

如果不想手动维护iptables配置,可以修改Docker的systemd服务文件,让Docker启动前自动添加这条规则:

  1. 编辑Docker的systemd服务文件:
    vi /usr/lib/systemd/system/docker.service
    
  2. ExecStart行之前添加以下内容:
    ExecStartPre=/sbin/iptables -A FORWARD -i docker0 -o docker0 -j ACCEPT
    
  3. 重新加载systemd配置并重启Docker:
    systemctl daemon-reload
    systemctl restart docker
    
    这样每次Docker启动都会自动配置好这条规则,一劳永逸。

额外说明:为什么会出现这个问题?

当禁用userland-proxy后,Docker会把端口转发规则写入iptables的DOCKER链,但默认的FORWARD链策略是拒绝未明确允许的流量。容器尝试通过主机IP访问转发端口时,流量会从docker0接口进入主机,再从docker0接口回到另一个容器,这条路径的流量默认被FORWARD链阻止,所以我们需要手动添加规则允许它。


你的环境信息:

[root@AppServer ~]# docker version
Client:
Version: 18.03.1-ol
API version: 1.37
Go version: go1.9.4
Git commit: 0d51d18
Built: Wed Aug 22 21:59:42 2018
OS/Arch: linux/amd64
Experimental: false
Orchestrator: swarm

Server:
Engine:
Version: 18.03.1-ol
API version: 1.37 (minimum version 1.12)
Go version: go1.9.4
Git commit: 0d51d18
Built: Wed Aug 22 22:03:05 2018
OS/Arch: linux/amd64
Experimental: false
[root@AppServer ~]#

内容的提问来源于stack exchange,提问作者Ram

火山引擎 最新活动