Docker之八----容器之间互联与网络模式详解

容器之间的互联

1、容器互联介绍

即在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问 ,比如一个业务前端静态页面是使用nginx,动态页面使用的是tomcat由于容器在启动的时候其内部IP地址是DHCP随机分配的,所以如果通过内部访问的话,自定义名称是相对比较固定的,因此比较适用于此场景。

2、部署容器互联

1、先创建第一个tomcat容器,后续需要将nginx进行转发到此tomcat服务上,tomcat测试页面在Docker之七已经创建,详情请见上一章!!!

[root@centos-7 ~]# docker run -it -d  --name tomcat1 tomcat-app1:v1
dd097a9fd8baaa2da451c279bd9a008c3b7ec36c6cf4a032aa40e697aec549f7

进入到tomcat服务里,查看tomcat的hosts文件

[root@centos-7 ~]# docker exec -it tomcat1 bash
[root@dd097a9fd8ba /]# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	dd097a9fd8ba  #tomcat的hosts文件解析
1.2.1.3 www.google.net

2、开启一个nginx容器,并将tomcat容器关联起来,启动nginx服务。

[root@centos-7 ~]# docker run -it -d --name nginx-web1 -p 80:80  --link tomcat1 nginx:v1
24549e8fac8fade868004fe6a5c0bc25f04abc08e82f1acffc8c1fcb47e6df65

3、进入nginx服务,然后看nginx的hosts文件

[root@centos-7 ~]# docker exec -it nginx-web2 bash
[root@1e2556622e7b /]# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	tomcat1 dd097a9fd8ba  #可以看到已经将tomcat的host文件关联过来
172.17.0.2	1e2556622e7b

 4、进入到nginx配置服务器,然后修改nginx的配置文件,进行转发的tomcat容器部分

[root@centos-7 ~]# docker exec -it nginx-web2 bash
[root@f53f3ba8b1ad /]# vim /etc/nginx/nginx.conf  #修改nginx服务
    upstream tomcat  {   #http段进行修改
        server tomcat:8080; #转发到tomcat服务的IP地址和端口,直接转发域名,关联的tomcat服务器的名称不变,就会一直转发到tomcat服务器上
    }

 
        location /app1 {    # server段进行修改
        proxy_pass http://tomcat;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-FOR $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        }

[root@f53f3ba8b1ad /]# nginx -t  # 测试语法
[root@f53f3ba8b1ad /]# nginx -s reload  #重新加载nginx

upstream段转发hosts域名,link链接tomcat的名称,就算tomcat容器删除,IP地址变化之后也没事,只需要重新进行link到同一个名称即可,这样就不需要修改nginx服务器内部配置文件,依然可以访问页面。 

此时访问宿主机的IP地址下的app1目录,就会访问到网页:

  

定义别名:

上一步骤中,自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,程序之间也要随之发生变化,比如程序通过容器名称进行服务调用,但是容器名称发生变化之后再使用之前的名称肯定是无法成功调用,每次都进行更

改的话又比较麻烦, 因此可以使用自定义别名的方式解决,即容器名称可以随意更改,只要不更改别名即可,具体如下:

命令格式:

docker run -d -name 新容器名称 --link 目标容器名称:自定义的名称 -p 本地端口:容器端口 镜像名称 shell 命令

1、重新创建一个tomcat容器,并启动。

[root@centos-7 src]# docker run -it -d --name tomcat2 tomcat-app1:v1

2、将nginx容器与tomcat容器关联,并起一个容器别名,别名为tomcat.google.com

[root@centos-7 ~]# docker run -it -d --name nginx-web3 -p 82:80  --link tomcat2:tomcat.google.com nginx:v1

3、进入nginx容器内,修改nginx配置文件

[root@centos-7 ~]# docker exec -it nginx-web4 bash
[root@faf64ae3e99b /]# vim /etc/nginx/nginx.conf       
     location /app1 {
           proxy_pass http://tomcat.google.com:8080; #直接监听别名解析
        }

[root@faf64ae3e99b /]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@faf64ae3e99b /]# nginx -s reload

测试页面,此时容器启动nginx监听的是82端口,因此需要82端口进行访问:

 

网络模式

通过网络夸宿主机互联:

同一个宿主机之间的各容器之间是可以直接通信的,但是如果访问到另外一台宿主机的容器呢?

下面我来介绍一下docker网络模式:

用命令直接查看网络模式:bridge、host、none、container四种模式。

1、Host网络模式

Host模式,使用参数--net=host指定,Host模式不支持端口映射,且容器无法启动。

启动的容器如果指定了使用host模式,那么新创建的容器不会创建自己的虚拟网卡(Network Namespace),而是直接使用宿主机的网卡和IP地址(Network Namespace),因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,不过容

器的其他资源们必须文件系统、系统进程等还是和宿主机保持隔离。此模式的网络性能最高,但是各容器之间端口不能相同,适用于运行容器端口比较固定的业务。

演示Host模式

[root@centos-7 ~]# docker run -it -d  --name nginx-net-host --net=host nginx:v1  # 打开指定host模式的容器
ac4e0be49a668d19935d9158e7e6a1c81c7afeac0d3dde88349979ab26e311dc
[root@centos-7 ~]# docker exec -it nginx-net-host bash # 进入到容器中
[root@centos-7 /]# ip a  #查看此host容器模式的IP地址,就是使用的是宿主机的IP地址
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:59:4a:1d brd ff:ff:ff:ff:ff:ff
    inet 192.168.7.100/24 brd 192.168.7.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe59:4a1d/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:a6:2c:bb:07 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:a6ff:fe2c:bb07/64 scope link 
       valid_lft forever preferred_lft forever

2、None网络模式

 使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,只有lo 网络接口。需要我们自己为Docker容器添加网卡、配置IP等。

 不参与网络通信,运行于此类容器中的进程仅能访问本地回环接口;仅适用于进程无须网络通信的场景中,例如:备份、进程诊断及各种离线任务等,此模式极少使用。

演示None模式

[root@centos-7 ~]# docker run -it -d --name nginx-net-host1 --net=none nginx:v1  # 创建none网络模式
dd00a68d3853602902aae3b08f57c06827b649f764f951a60bc7e4c2298a0ea4
[root@centos-7 ~]# docker exec -it nginx-net-host1 bash
[root@dd00a68d3853 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
[root@dd00a68d3853 /]# ifconfig
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

3、Container网络模式  

Container模式介绍

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

网络示意图:

 

 (1)在一个终端,使用bridge网络模式启动容器tomcat1

[root@centos-7 ~]# docker run -it --name tomcat1 --net=bridge  -d tomcat-app1:v1
10753fcfcd45b06eac55badca2166dcca5c76e26260d99bfa945f68ae8a50454
[root@centos-7 ~]# docker exec -it tomcat1 bash
[root@10753fcfcd45 /]# ip a  #查看此时的IP地址是172.17.0.2
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

(2)在另一个终端使用Container 网络模式创建容器tomcat2 

[root@centos-7 ~]# docker run -it -d -name tomcat2 --net=container:tomcat1 tomcat-app1:v1  # 创建tomcat2容器
[root@centos-7 ~]# docker exec -it tomcat2 bash  #进入到tomcat2
[root@10753fcfcd45 /]# ip a   # 查看IP地址,此时的IP地址就和桥接模式的IP地址一致
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

4、Bridge 网络模式

 介绍

  当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上,所以有默认地址172.17.0.0/16的地址。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

  从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

 

[root@centos-7 ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242a62cbb07	no		veth4f25042

bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。

[root@centos-7 ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 31 packets, 5027 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   31  1588 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 31 packets, 5027 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 69 packets, 4024 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 69 packets, 4024 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  233 14471 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0  

Docker跨主机(不同网段)互联之简单实现 

环境准备 

A主机:10.20.0.1/16

B主机:10.10.0.1/16

在A主机修改Docker0地址

1、修改A主机的docker配置文件,指定docker容器的IP地址

[root@openstack ~]# vim /lib/systemd/system/docker.service 
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  --bip 10.20.0.1/16

[root@openstack ~]# systemctl daemon-reload
[root@openstack ~]# systemctl restart docker

2、查看此时修改后的docker0的IP地址,此时就是修改后的IP地址

 

 在B主机修改Docker0地址

 1、修改B主机的docker地址,指定一个地址10.10.0.1/16

[root@centos-7 ~]# vim  /lib/systemd/system/docker.service 
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  --insecure-registry 192.168.7.103 --insecure-registry 192.168.7
.102    --bip=10.10.0.1/16

[root@centos-7 ~]# systemctl daemon-reload
[root@centos-7 ~]# systemctl restart docker

2、查看修改后的IP地址

  

 在两个宿主机分别开启一个容器

1、A主机开启一个容器

[root@centos-7 ~]# docker run -it -d --name nginx-web1 nginx:v1
7a77bc53509d6e14f25b5a217e1b47ccf8af61ac7e6011786512131c6803a16f

2、B主机开启一个容器

[root@openstack ~]# docker run -it -d --name nginx-web2 goharbor/harbor-db:v1.7.5

添加静态路由 

1、在A主机添加B主机的IP地址段和B主机的宿主机IP地址,并添加一个防火墙规则

[root@centos-7 src]# route add -net 10.20.0.0/16 gw 192.168.7.102
[root@centos-7 src]# iptables  -A FORWARD  -s 192.168.7.0/21  -j ACCEPT  #允许此IP地址段的都可以访问

2、在B主机添加A主机的IP地址段和A主机的宿主机IP地址,并添加防火墙规则

[root@centos-7 src]# route add -net 10.10.0.0/16 gw 192.168.7.102
[root@centos-7 src]# iptables  -A FORWARD  -s 192.168.7.0/21  -j ACCEPT  #允许此IP地址段的都可以访问

3、进入A主机开启的容器内部,然后ping测试B主机是否能够ping通

[root@centos-7 ~]# docker exec -it nginx-web1 bash

[root@7a77bc53509d /]# ping 10.10.0.1
PING 10.10.0.1 (10.10.0.1) 56(84) bytes of data.
64 bytes from 10.10.0.1: icmp_seq=1 ttl=64 time=0.078 ms
64 bytes from 10.10.0.1: icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from 10.10.0.1: icmp_seq=3 ttl=64 time=0.050 ms
64 bytes from 10.10.0.1: icmp_seq=4 ttl=64 time=0.049 ms

4、此时B主机ping A主机也可以通

[root@openstack ~]# docker exec -it 8b86881da848  bash
root [ / ]# ping 10.20.0.1
PING 10.10.0.2 (10.10.0.2) 56(84) bytes of data.
64 bytes from 10.10.0.2: icmp_seq=1 ttl=62 time=0.700 ms
64 bytes from 10.10.0.2: icmp_seq=2 ttl=62 time=0.485 ms
64 bytes from 10.10.0.2: icmp_seq=3 ttl=62 time=0.465 ms

实现自定义网络

1、创建一个网络名称

[root@centos-7 ~]# docker network create -d bridge  --subnet 172.27.0.0/21  --gateway 172.27.0.1 linux36-net

 查看创建成功的网络信息,此时可以看到linux36-net就是自己创建的网络

[root@centos-7 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f2926808018e        bridge              bridge              local
7706b813f5bf        host                host                local
4e9a106f0e22        linux36-net         bridge              local
498b37d89d4e        none                null                local

2、运行一个centos镜像,此时就可以看到一个自定义的网络分配给镜像一个IP地址

[root@centos-7 ~]# docker run -it --network linux36-net centos bash  # 使用自己创建的网络IP地址段
[root@8409e98a804d /]# ip a  # 拿到的IP地址是172.27.0.2/21
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
55: eth0@if56: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.27.0.2/21 brd 172.27.7.255 scope global eth0
       valid_lft forever preferred_lft forever

3、此时就可以ping通外网的地址

[root@8409e98a804d /]# ping www.baidu.com
PING www.a.shifen.com (112.80.248.75) 56(84) bytes of data.
64 bytes from 112.80.248.75 (112.80.248.75): icmp_seq=1 ttl=127 time=32.6 ms
64 bytes from 112.80.248.75 (112.80.248.75): icmp_seq=2 ttl=127 time=50.3 ms

4、此时再启动一个容器A,查看最新的容器IP地址,由于和上面创建的容器,在一个地址段,因此也可以进行通信

[root@centos-7 src]# docker run -it -p 80:80 --network linux36-net nginx:v1 bash
[root@b3afcaea2c02 /]# ip a  #查看新建的容器的IP地址是172.27.0.3,在同一个网段。
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
61: eth0@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:1b:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.27.0.3/21 brd 172.27.7.255 scope global eth0
       valid_lft forever preferred_lft forever

5、为了将两个跨主机且不在同一网段的宿主机进行通信

[root@centos-7 src]# iptables-save > iptables-rule.txt  #将iptables规则导出,然后修改此配置文件,注释掉以下两行
#-A DOCKER-ISOLATION-STAGE-2 -o br-4e9a106f0e22 -j DROP
#-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP

[root@centos-7 src]# iptables-restore  < iptables-rule.txt  # 再将iptables规则再导回来

6、然后开启个桥接模式的容器B

[root@centos-7 src]# docker run -d  -it -p 81:80 --network bridge  nginx:v1  #启动一个桥接模式的容器
0274bd84109ae248d74af702b76d69227f3ccc9b45948d5595ae9fb32fe5439a
[root@centos-7 src]# docker exec -it 0274bd84109ae248d74af702b76d69227f3ccc9b45948d5595ae9fb32fe5439a bash
[root@0274bd84109a /]# ip a  # 获取的IP地址是10.10.0.3/16
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
65: eth0@if66: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:0a:0a:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.10.0.3/16 brd 10.10.255.255 scope global eth0
       valid_lft forever preferred_lft forever

7、然后进入容器B中进行ping容器A的IP地址,此时就会基于iptables规则进行跨网段ping通

[root@centos-7 src]# docker run -d  -it -p 81:80 --network bridge  nginx:v1 
0274bd84109ae248d74af702b76d69227f3ccc9b45948d5595ae9fb32fe5439a
[root@centos-7 src]# docker exec -it 0274bd84109ae248d74af702b76d69227f3ccc9b45948d5595ae9fb32fe5439a bash  # 进入到B容器中
[root@0274bd84109a /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
65: eth0@if66: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:0a:0a:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.10.0.3/16 brd 10.10.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@0274bd84109a /]# ping 172.27.0.3  #ping容器A的IP地址,此时可以ping通
PING 172.27.0.3 (172.27.0.3) 56(84) bytes of data.
64 bytes from 172.27.0.3: icmp_seq=1 ttl=63 time=0.335 ms
64 bytes from 172.27.0.3: icmp_seq=2 ttl=63 time=0.069 ms
64 bytes from 172.27.0.3: icmp_seq=3 ttl=63 time=0.070 ms
^C
--- 172.27.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.069/0.158/0.335/0.125 ms

  

  

  

  

  

  

 

  

  

  

  

 

 

 

猜你喜欢

转载自www.cnblogs.com/struggle-1216/p/12205059.html