如何在window配置host( 二 )


在容器中运行 ping sohucom 或 ping 1921680200 都可以ping通 。
默认情况下,不需要再额外做任何配置 , 在一台host主机上 , 通过docker0,各容器之间可以互通,并且可以通过host的eth0连接外网 。
通俗的讲,通过docker0组成了一个网段为1721700/16的以太网,docker容器发起请求时,如果是相同网段则经由docker0转发到目标机器,如果是不同网段,则经由docker0,转发到host的另一块网卡eth0上,由eth0负责下一步的数据包转发 , 比如公网地址 。
下面进一步分析一下报文是怎么发送到外面的 。
容器内部发送一条公网请求报文,通过eth0,在veth被接收 。此时报文已经来到了主机上,通过查询主机的路由表( route -n ),如果发现报文应该通过主机的eth0,从默认网关发送出去,那么报文就被从docker0转发给主机的eth0,但前提是首先启用ip_forward功能,才能在host主机的docker0和eth0两个网卡间传递数据包 。
由于目标地址并不属于host主机所在网段,那么会匹配机器上的 iptables中的nat表POSTROUTING链中的规则 。
在host主机运行命令 iptables -L -n -t nat --line-numbers ,查看nat表,这里只看POSTROUTING链:
第一行中说明 , 对于源地址为1721700/16网段的数据包,发出去之前通过MQSQUERADE伪装 。linux内核会修改数据包源地址为host主机eth0的地址(也就是1921680200),然后把报文转发出去 。对于外部来说,报文是从主机eth0发送出去的 。
局域网内的机器由于都是私有IP,是无法直接访问互联网的(数据包可以发出去,但回不来 。)如果要上网,除了可以通过硬件路由器,也可以通过软件路由,在iptables的nat表中的POSTROUTING链中添加SNAT规则 。
测试一下,在host主机运行命令 iptables -t nat -D POSTROUTING 1 将第一条规则删掉 , 那么在容器中就运行命令 ping sohucom 就ping不通了 。但仍然可以ping通host主机 。
在host主机运行命令以下命令恢复:
iptables -t nat -I POSTROUTING -s 1721700/16 -o eth0 -j SNAT --to-source 1921680200
或者
iptables -t nat -I POSTROUTING -s 1721700/16 -j MASQUERADE
关于SNAT和MASQUERADE,这篇文章已经有过描述,可以参考: Docker前传之linux iptables
新建一Dockerfile,用以运行nginx容器:
# Version: 001 FROM paulliu/ubuntu_ip RUN apt-get install -y nginx EXPOSE 80
在host主机运行构建命令构建镜像 docker build -t paulliu/nginx
在host主机运行容器启动命令 docker run -d -p 80 --name nginx1 paulliu/nginx nginx -g "daemon off;"
在host主机查看容器的端口映射 docker port nginx1 80
在host主机运行命令 iptables -nat -L -n 可以看到在PREROUTING链中多了以下DNAT规则:
也就是在容器启动时通过 -p 80 将host主机1921680200:32773映射为容器1721704:80 。