Docker容许经过外部访问容器或容器互联的方式来提供网络服务。docker
当Docker启动时,会在主机上建立一个 docker0虚拟网桥,其实是Linux的一个bridge,能够理解为一个软件交换机。它会在挂载到它的网口之间进行转发。安全
同时,Docker随机分配一个本地未占用的私有网段中的一个地址给docker0接口。好比典型的172.17.42.1,掩码为255.255.0.0 。此后启动的容器内网口也会自动分配一个统一网段的地址(172.17.0.0/16)的地址。当建立一个Docker容器的时候,同时会建立一对 veth pair接口(当数据包发送到一个接口时,另一个接口也能够收到相同的数据包)。这对接口一端在容器内,即eth0,另一端在本地并被挂载到docker0网桥,名称以veth开头。经过这种方式,主机能够跟容器通讯,容器之间也能够相互通讯。docker就建立了在主机和全部容器之间的一个虚拟网络。网络
容器之间访问tcp
容器之间相互访问,须要两方面的支持:工具
1.容器的网络拓扑图是否互联。默认状况下,全部容器都会被链接到docker0网桥上。接口
2.本地系统的防火墙软件-- iptables是否容许经过。ip
访问全部端口:get
当容器启动的时候,默认会添加一条转发策略到iptables的forward链上。策略为经过(accept)仍是禁止(drop)取决于配置--icc=true(缺省值)仍是 -icc=false。io
可见默认状况下,不一样容器之间是容许网络互通的。若是为了安全考虑,能够在/etc/default/docker 文件配置中 docker opts=--icc=false来禁止。table
访问指定端口
在经过-icc=false关闭网络访问后,还能够经过--link=container_name:alias 选项来访问容器的开放端口。
docker提供了 --link:容器名:别名来指定要和哪一个容器通讯。docker会在iptable中为两个容器分别添加一条accept,容许访问开放的端口(取决于Docfile中的expose指令)。
映射容器端口到宿主机的实现
容器访问外部网络
容器要想访问外部网络,须要本地系统的转发支持。容器全部到外部网络的链接,源地址都会被NAT成本地网络的IP地址。这是使用 iptables的源地址假装操做来实现的。查看主机的NAT规则: sudo iptables -t nat -nL。能够看到,规则将全部源的地址在172.17.0.0/16网段,目标地址为其余网段(外部网络)的流量动态假装为从系统网卡发出。MASQUERAD跟传统的SNAT的好处是它能动态从网卡获取地址。
在Linux系统中,检查转发是否打开。
执行: sysctl net.ipv4.ip_forward
输出: net.ipv4.ip_forward = 1 ,若是为0,说明没有开启转发,须要手动打开。执行 sysctl -w net.ipv4.ip_forward=1。若是在启动docker服务的时候设定 --ip-forward=true,Docker就会自动设定系统的ip_forward参数为1。
在宿主机执行 docker inspect kibana,查看运行容器的ip
而后在宿主机ping容器的IP ping 172.18.0.1,发如今宿主机能够ping通容器。反之在容器内也能够ping通宿主机。(容器内安装ping工具包 apt-get install iputils-ping)。 由此能够,默认状况下主机和容器是互通的。 容器的ip在启动的时候分配,不过在容器从新启动以后,ip会发生变化。
在相同主机直接的容器也是能够相互通讯的。
外部访问容器实现
容器容许外部访问,能够在docker run的时候经过 -p 或者-P参数来启用。无论用那种方式,其实也是在本地的iptables的nat表中添加相应的规则.
使用 -p 6379:6379 时: iptables -t nat -nL
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:6379 to:172.18.0.2:6379
这里规则映射了0.0.0.0,意味着将接受主机来自全部接口的流量。用户能够经过 -p IP:host_port:container_port或者 -ip IP::port 来制定容许访问容器的主机上的IP,接口等。