容器内访问外网
只要宿主机能访问外网,那么天生的容器就能自然而然的访问外网。假如你的容器访问不了外网,那么就需要知道容器能访问外网是怎么做到的,然后再去排查问题。
这是宿主机和容器之间采用了 ip_forward 技术,那么什么是 ip_forward,请看这篇文章:ip_forward与路由转发。不过这篇文章讲得比较深奥,我是没有太看明白,只是明白了这么一点浅显的道理:内网、容器、虚拟机要访问外网,那么在网关(针对内网)、宿主机(针对容器、虚拟机)上要设置 ip_forward。
内网 --> 网关 --> 外网 : 那么需要在网关上设置ip_forward
容器 --> 宿主机 --> 外网 : 那么需要在宿主机上设置ip_forward
虚拟机 --> 宿主机 --> 外网 : 那么需要在宿主机上设置ip_forward
在宿主机上查看 ip_forward 有没有打开的方法:
cat /proc/sys/net/ipv4/ip_forward
或者
sysctl net.ipv4.ip_forward
对于sysctl,可以查看这篇文章:《lsmod,modprobe和sysctl的说明》
在docker安装的时候,安装程序会将 net.ipv4.ip_forward 设置为1,同时安装程序进一步会将 net.ipv4.conf.all.forwarding 也设置为1。
我估计对于虚拟机的安装程序来说,也会有这样的操作。
容器之间的互联
这里只讲在一台机器上的容器之间通信,同时不涉及以下情况:
1. 不涉及:参见我以前的博文《docker容器之间通过link方式的互联》
2. 不涉及 docker network create 创建的容器之间的网络
3. 不涉及 overlap 网络,比如 ingress 和 flannel
比如有2个容器,a容器的ip是 172.17.0.2(其中有一个nginx,对外暴露了80端口),b容器的ip是 172.17.0.3 ,那么在 b容器中:
telnet 172.17.0.2 80
OK,没有问题。
所以,在一台机器内的容器,只要2个都属于同一个 虚拟 bridge,比如默认的 docker0,那么通过IP互联没有任何问题。
容器通过宿主机的IP和端口去访问另一个容器对外暴露的端口
上面这句话很绕口,我们来举个例子:
宿主机的IP是 192.168.1.100
a容器内有一个nginx,对外暴露了80端口,比如 docker run -d -p 80:80 nginx
在b容器内进行:
ping 192.168.1.100 #OK,没有问题,说明能访问到宿主机
telnet 192.168.1.100 80 #不行了,说明能访问到宿主机,但是因为宿主机的防火墙给挡住了
那么我们修改一下宿主机的iptables,让来自 docker0 这个虚拟网卡的流量能通行:
iptables -I INPUT chainnumber -i docker0 -j ACCEPT
以后修改iptables尽量不要用 iptables -A,因为 iptables 的策略中有可能最后一条是 reject all,所以必须要插在 reject all 这一条之前。
那么上面中的 chainnumber 用 iptables -L -n –line-numbers 来查看,具体大家可以去查互联网资料。
修改后iptables后,这样就可以在b容器访问宿主机的某个容器暴露端口了。