容器之间的互联
在同一个宿主机上的容器之间可以通过端口映射的方式经过宿主机中转进行互相访问
也可以直接通过宿主机的docker0网桥进行互相访问
直接互联
- 启动两个Nginx容器
[root@server ~]# docker run -d -it --name nginx-1 nginx[root@server ~]# docker run -d -it --name nginx-2 nginx
- 安装相关工具包,用来查看IP地址并且进行互ping测试
root@root@1bc3c795b000:/# apt updateroot@root@1bc3c795b000:/# apt install net-tools -yroot@root@1bc3c795b000:/# apt install iputils-ping -yroot@root@1bc3c795b000:/# apt install procps -y
- 查看各自的IP地址
# nginx-1root@1bc3c795b000:/# ifconfig # 172.17.0.2# nginx-2root@4e305588f142:/# ifconfig # 172.17.0.3
- 直接互ping是可以连通的
root@1bc3c795b000:/# ping 172.17.0.3 -c 2PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.072 ms64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.204 ms--- 172.17.0.3 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 1002msrtt min/avg/max/mdev = 0.072/0.138/0.204/0.066 ms
名称互联
- 启动两个Nginx容器
[root@server ~]# docker run -d -it --name nginx-1 nginx[root@server ~]# docker run -d -it --name nginx-2 --link nginx-1 nginx
- 查看nginx-2容器的hosts文件,发现已经实现了主机名解析
[root@server ~]# docker exec -it nginx-2 bashroot@7385ecc0af3a:/# cat /etc/hosts127.0.0.1 localhost::1 localhost ip6-localhost ip6-loopbackfe00::0 ip6-localnetff00::0 ip6-mcastprefixff02::1 ip6-allnodesff02::2 ip6-allrouters172.17.0.2 nginx-1 8cfad88ba05a # 容器nginx-1172.17.0.3 7385ecc0af3a
- 因此直接进行ping主机名也是可以通的
root@7385ecc0af3a:/# ping nginx-1 -c 2PING nginx-1 (172.17.0.2) 56(84) bytes of data.64 bytes from nginx-1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.180 ms64 bytes from nginx-1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.100 ms--- nginx-1 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 1000msrtt min/avg/max/mdev = 0.100/0.140/0.180/0.040 ms
别名互联
自定义的容器名称可能后期会发生变化,那么一旦发生变化也会带来一些影响,这个时候如果每次都更改名称又比较麻烦,这个时候可以使用定义别名的方式解决,即容器名称可以随意更改,只要不更改别名即可
- 启动两个Nginx容器
[root@server ~]# docker run -d -it --name nginx-1 nginx[root@server ~]# docker run -d -it --name nginx-2 --link nginx-1:web1 nginx
- 查看nginx-2容器的hosts文件,发现已经实现了主机名解析,同时别名也进行了解析
[root@server ~]# docker exec -it nginx-2 bashroot@1241479e8e4f:/# cat /etc/hosts127.0.0.1 localhost::1 localhost ip6-localhost ip6-loopbackfe00::0 ip6-localnetff00::0 ip6-mcastprefixff02::1 ip6-allnodesff02::2 ip6-allrouters172.17.0.2 web1 1e96a855597b nginx-1172.17.0.3 1241479e8e4f
- 直接进行ping别名同样是可以通的
root@1241479e8e4f:/# ping web1 -c 2PING web1 (172.17.0.2) 56(84) bytes of data.64 bytes from web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.075 ms64 bytes from web1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.085 ms--- web1 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 1000msrtt min/avg/max/mdev = 0.075/0.080/0.085/0.005 ms
Docker网络
网络模式介绍
| Docker网络模式 | 配置 | 说明 |
|---|---|---|
| none模式 | —network none | 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,配置IP等 |
| container模式 | —network container:容器名/ID | 容器和另外一个容器共享Network namespace;kubernetes中的pod就是多个容器共享一个Network namespace |
| host模式 | —network host | 容器和宿主机共享Network namespace |
| bridge模式 | —network bridge | 默认模式,容器与宿主机桥接 |
None模式
- 使用None模式后,docker容器不会进行任何网络配置,没有网卡没有IP也没有路由,因此默认无法与外界进行通信,需要手动添加网卡配置IP等,因此极少使用这种模式

启动一个none网络模式的容器,可以看到没有IP地址,只有一个环回接口
[root@server ~]# docker run -d --name web1 --network none nginx:v13d6e13c3bd8bbad49a2689c184bc530629071413a5e78e5d68c5cff9abaf9de5[root@server ~]# docker exec -it web1 bash[root@3d6e13c3bd8b /]# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
Container模式
Container模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享
新创建的容器不会创建自己的网卡,配置自己的IP,而是和指定的容器共享一个IP、端口范围等
两个容器除了网络方面不是隔离的,其他方面如文件系统、进程列表等还是隔离的

启动一个默认模式的容器,一个container模式的容器
[root@server ~]# docker run -d --name web1 nginx:v1[root@server ~]# docker run -d -it --name web2 --network container:web1 centos:7
进入两个容器查看各自的IP地址,发现IP地址是一样的,暴露的端口也是一样的,而他们的主机名也是一模一样的
[root@server ~]# docker exec -it web1 bash[root@b30a2eb148c5 /]# ip a# eth0:172.17.0.2[root@b30a2eb148c5 /]# ss -tnlState Recv-Q Send-Q Local Address:Port Peer Address:PortLISTEN 0 128 *:80 *:*[root@server ~]# docker exec -it web2 bash[root@b30a2eb148c5 /]# ip a# eth0:172.17.0.2[root@b30a2eb148c5 /]# ss -tnlState Recv-Q Send-Q Local Address:Port Peer Address:PortLISTEN 0 128 *:80 *:*
Host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace
容器不会虚拟出自己的网卡,配置自己的IP等,而是直接使用宿主机的IP和端口
使用host模式的容器可以直接使用宿主机的IP地址和外界进行通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT
host模式的优点就是网络性能很好,但是对于宿主机和容器之间的网络隔离性来说不是很友好

启动两个host模式的容器
[root@server ~]# docker run -d -it --name web1 --network host centos:7[root@server ~]# docker run -d -it --name web2 --network host centos:7
进入容器内部(看似没进入,实则已经进去了,因为主机名是一样的)
[root@server ~]# docker exec -it web1 bash[root@server /]#
查看网络配置信息,可以发现和宿主机上的网络配置信息一模一样
# 宿主机[root@server ~]# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:31:70:df brd ff:ff:ff:ff:ff:ffinet 192.168.31.99/24 brd 192.168.31.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet6 fe80::ea13:321a:474b:f3ea/64 scope link noprefixroutevalid_lft forever preferred_lft forever3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group defaultlink/ether 02:42:37:35:35:d7 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:37ff:fe35:35d7/64 scope linkvalid_lft forever preferred_lft forever# 容器web1或者web2[root@server /]# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:31:70:df brd ff:ff:ff:ff:ff:ffinet 192.168.31.99/24 brd 192.168.31.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet6 fe80::ea13:321a:474b:f3ea/64 scope link noprefixroutevalid_lft forever preferred_lft forever3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group defaultlink/ether 02:42:37:35:35:d7 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:37ff:fe35:35d7/64 scope linkvalid_lft forever preferred_lft forever
包括端口信息也是一模一样

Bridge模式
- 当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上,虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中
- 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关,然后在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过
brctl show命令查看

- bridge模式是docker的默认网络模式,容器启动时不写—network参数就是bridge模式
- 使用docker run -p端口映射时,底层工作的是iptables,它实现了端口转发功能,可以通过iptables -t nat -vnL进行查看,当docker服务启动的时候,就会自动在iptables中新增一个自定义链Chain DOCKER

注意点:
有时候docker服务在运行的时候,会发现防火墙没关,此时就会使用
systemctl stop firewalld关闭防火墙,那么此时iptables中的DOCKER链就也会被清空,那么端口映射就会出错了!此时的解决办法是重启docker服务systemctl restart docker,那么DOCKER链就又会自动回来了
自定义网络
可以使用docker命令来创建自定义网络,自定义网络可以自定义IP地址范围和网关等信息
- 创建一个网络
[root@server ~]# docker network create -d bridge --subnet 10.10.0.0/16 --gateway 10.10.0.1 my-net6a1eaa02a995581fda7939222fac54740877e35688b1ffd9f98e42fb624e3d25[root@server ~]# docker network listNETWORK ID NAME DRIVER SCOPEbda7c30ac2ac bridge bridge local8d5ae5100941 host host local6a1eaa02a995 my-net bridge localf8073bd77b21 none null local

- 使用自定义的网络创建容器
[root@server ~]# docker run -d -it --name web1 --network my-net nginx:v14ffa06be05c8c356cfce5be166d4b62371f916afc443316d88b9ddb11057e7bb
- 进入容器查看网络配置
[root@server ~]# docker exec -it web1 bash[root@4ffa06be05c8 /]# ip a# eth0:10.10.0.2[root@4ffa06be05c8 /]# ping baidu.com -c 2# 能ping通
- 查看iptables的nat表
[root@server ~]# iptables -t nat -vnL

