五、docker容器的网络访问
默认情况下,容器使用的ip是172.17.0.0/16网段的,外界的用户只能访问宿主机的192.168.32.0/24网段,无法访问172.17.0.0/16网段。我们运行容器的目的:是希望运行在容器中的服务,能够被外界访问,这里就涉及到了外网192.168.32.0/24到容器内网172.17.0.0/16网段的转换,所以需要做端口映射。
二、docker运行容器端口映射的方法
指定映射(docker 自动添加一条iptables规则实现端口映射) -p hostPort:containerPort -p ip:hostPort:containerPort -p ip::containerPort(随机端口) -p hostPort:containerPort:udp -p 81:80 -p 443:443 可以指定多个-p 随机映射 docker run -P (随机端口) iptables [root@inode3 ~]# iptables -t nat -L -n Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80 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:80 to:172.17.0.2:80 #容器172.17.0.2的tcp80端口已经映射到了外网的80端口上
1、容器网络配置命令
docker run --name 运行的容器名称 --net=网络参数选项 -p 容器端口映射 镜像名称:镜像版本
--net=网络参数选项
None:不为容器配置任何网络功能,--net=none Container:与另一个运行中的容器共享Network Namespace,--net=container:containerID Host:与主机共享Network Namespace,--net=host Bridge:Docker设计的NAT网络模型
docker网络查看命令
[root@inode4 ~]#docker network ls NETWORK ID NAME DRIVER SCOPE a736b9bf0850 bridge bridge local db0ed8b2be23 host host local 0339ee737df3 mac1 macvlan local 90c917be552d none null local
docker容器的网络通信原理:
1、 当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上,所以有默认地址172.17.0.0/16的地址。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
[root@inode4 ~]# ifconfig docker0 docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:8cff:fe57:ebf8 prefixlen 64 scopeid 0x20<link> ether 02:42:8c:57:eb:f8 txqueuelen 0 (Ethernet) RX packets 194130 bytes 20622371 (19.6 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 250033 bytes 780264041 (744.1 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
2、 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
yum install -y bridge-utils-1.5-9.el7.x86_64 [root@inode4 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.02428c57ebf8 no veth16bb7cf #宿主机中docker0的网卡 vethccb0469 #容器的网卡(在容器中eth0)
bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。
[root@inode3 ~]# iptables -t nat -L -n Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80 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:80 to:172.17.0.2:80 #容器172.17.0.2的tcp80端口已经映射到了外网的80端口上
docker bridge原理图
bridge案例
[root@inode3 ~]# docker run --net=bridge -it centos:6.9 /bin/bash [root@b796f4521c28 /]# ifconfig eth0 eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03 inet addr:172.17.0.3 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:508 (508.0 b) TX bytes:0 (0.0 b) [root@b796f4521c28 /]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
docker host原理图
host案例
[root@inode3 ~]# docker run -it --net=host centos:6.9 /bin/bash [root@inode3 /]# ifconfig eth0 eth0 Link encap:Ethernet HWaddr 00:0C:29:E2:7B:77 inet addr:192.168.32.103 Bcast:192.168.32.255 Mask:255.255.255.0 inet6 addr: fe80::dceb:89ad:3d37:bebe/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:603672 errors:361 dropped:444 overruns:0 frame:0 TX packets:245020 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:795145514 (758.3 MiB) TX bytes:20746259 (19.7 MiB)
发现ip与宿主机的ip一样
第三种模式:Container 网络模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
docker container原理图
命令格式
docker run --name 运行容器名称 -d -p 容器的端口影身 --network container:共享网络的容器名 镜像:镜像版本
container案例
现有运行容器web1
[root@inode3 ~]# docker inspect web1 |grep -i "ipaddress" "SecondaryIPAddresses": null, "IPAddress": "172.17.0.2", "IPAddress": "172.17.0.2",
[root@inode3 ~]# docker run -it --name centos6.9 --network container:web1 centos:6.9 [root@7c5d1590be34 /]# ifconfig eth0 eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:17 errors:0 dropped:0 overruns:0 frame:0 TX packets:7 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1280 (1.2 KiB) TX bytes:1272 (1.2 KiB)
[root@7c5d1590be34 tmp]# touch ywx.log [root@7c5d1590be34 tmp]# ls anaconda-post.log yum.log ywx.log
第四种模式:none
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,只有lo 网络接口。需要我们自己为Docker容器添加网卡、配置IP等。
不参与网络通信,运行于此类容器中的进程仅能访问本地回环接口;仅适用于进程无须网络通信的场景中,例如:备份、进程诊断及各种离线任务等。
docker none原理图
[root@inode3 ~]# docker run -it --name centos6.9 --network none centos:6.9 /bin/bash [root@9703a325d77f /]# ifconfig eth0 eth0: error fetching interface information: Device not found [root@9703a325d77f /]# ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)