Docker网络--容器通信

容器通信除了可以使用ip以外,还可以使用容器名称进行通信
dns解析功能在自定义网络中才可以生效

Docker容器之间实现通信

1.启动容器使用–name指定容器的名称

[root@server1 ~]# docker network ls  ##查看当前网络
NETWORK ID          NAME                DRIVER              SCOPE
a3b785379510        bridge              bridge              local
66a8ce5625c5        host                host                local
0f283adad81f        my_net1             bridge              local
64ecaf807e64        my_net2             bridge              local
ebc2c1a28d75        none                null                local
[root@server1 ~]# docker run -it --name vm1 --network my_net1 ubuntu  ##以自定义网络my_net2创建容器vm1
root@9918b4adf65e:/# ip addr  ##查看分配ip为172.18.0.2
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
18: eth0@if19:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@server1 ~]# docker run -it --name vm2 --network my_net1 ubuntu  ##以自定义网络my_net2创建容器vm2
root@9d8a238d96cb:/# ip addr  ##查看分配ip为172.18.0.3
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
20: eth0@if21:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
root@9d8a238d96cb:/# ping vm1  ##通过dns解析,以容器名称实现通信功能
PING vm1 (172.18.0.2) 56(84) bytes of data.
64 bytes from vm1.my_net1 (172.18.0.2): icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from vm1.my_net1 (172.18.0.2): icmp_seq=2 ttl=64 time=0.058 ms
64 bytes from vm1.my_net1 (172.18.0.2): icmp_seq=3 ttl=64 time=0.049 ms
^C
--- vm1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.049/0.055/0.060/0.009 ms

2.容器之间实现网络共享
创建容器时使用–network=container:vm1指定(vm1运行容器的名称)

[root@server1 ~]# docker run -it --name vm1 ubuntu  ##创建容器1
root@655ab1b2369e:/# ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
22: eth0@if23:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@server1 ~]# docker run -it --name vm2 --network container:vm1 ubuntu
root@655ab1b2369e:/# ip addr 
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
22: eth0@if23:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

两容器ip地址完全相同均为172.17.0.2/16实现网络共享,处于这个模式下的容器会共享一个网络线,这样两个容器之间可以使用localhost实现高效快速的通信

3.容器之间实现链接
创建容器时使用–link,指定源容器的名称和id(作用:更新host文件,将原容器的变量设置到新容器)

[root@server1 ~]# docker run -d nginx  ##创建源容器
abbf190aca8c869211d1f2a858761b53b390f824c7216e9b3f6fdcd18137c801
[root@server1 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
abbf190aca8c        nginx               "nginx -g 'daemon of…"   9 seconds ago       Up 7 seconds        80/tcp              blissful_robinson
[root@server1 ~]# docker inspect abbf190aca8c  ##获取到的ip为172.17.0.2
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
[root@server1 ~]# docker run -it --name vm1 --link blissful_robinson:web ubuntu  ##新容器vm1链接源容器,并给源容器起名为web
root@32b018ee1ea7:/# ping web  ##与源容器实现通信
PING web (172.17.0.2) 56(84) bytes of data.
64 bytes from web (172.17.0.2): icmp_seq=1 ttl=64 time=0.105 ms
64 bytes from web (172.17.0.2): icmp_seq=2 ttl=64 time=0.052 ms
^C
--- web ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.052/0.078/0.105/0.027 ms
root@32b018ee1ea7:/# 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.2	web abbf190aca8c blissful_robinson  ##源容器ip,别名,id,原name
172.17.0.3	32b018ee1ea7  ##vm1容器ip及id
root@32b018ee1ea7:/# env  ##查看环境可知:将原容器的变量作为参数全部传输至vm1
HOME=/root
WEB_NAME=/vm1/web
WEB_PORT_80_TCP_PROTO=tcp
WEB_PORT_80_TCP_ADDR=172.17.0.2
LESSOPEN=| /usr/bin/lesspipe %s
WEB_PORT=tcp://172.17.0.2:80
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/env

–link自动更改解析文件hosts

[root@server1 ~]# docker stop  blissful_robinson  ##停止源容器
blissful_robinson
[root@server1 ~]# docker start blissful_robinson  ##开启源容器
blissful_robinson
[root@server1 ~]# docker inspect blissful_robinson  ##查看源容器信息
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",  ##ip依旧分配为172.17.0.2
[root@server1 ~]# docker stop  blissful_robinson  ##再次关闭源容器
blissful_robinson
[root@server1 ~]# docker run -d nginx  ##重新开启一个新的容器
1c4834e8777a8c34908fb3059c1e4b50725e9e4ab2028c518cd526dcc8f64714
[root@server1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
1c4834e8777a        nginx               "nginx -g 'daemon of…"   10 seconds ago      Up 9 seconds        80/tcp              jolly_leakey
32b018ee1ea7        ubuntu              "/bin/bash"              12 minutes ago      Up 12 minutes                           vm1
[root@server1 ~]# docker inspect  jolly_leakey
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2"  ##新容器ip为172.17.0.2占用源容器ip
[root@server1 ~]# docker start blissful_robinson  ##开启之前关闭的源容器
blissful_robinson
[root@server1 ~]# docker inspect  blissful_robinson
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.4",  ##此时源容器获取的ip为172.17.0.4
此时进入容器vm1中再次查看
root@32b018ee1ea7:/# 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.4	web abbf190aca8c blissful_robinson  ##web源ip被自动更改为172.17.0.4
172.17.0.3	32b018ee1ea7

容器访问外网

1.与外网实现通信的原理
Docker网络--容器通信_第1张图片
原理:
容器与docker0以桥接的方式连接,则docker0做为容器的网关,数据到达docker0网关;docker0与宿主机之间通过内核路由功能实现通信,则数据经过内核路由功能并转换为当前宿主机的地址到达宿主机;由宿主机将数据包传达至外网

[root@server1 ~]# iptables -t nat -S  ##查看火墙策略
-A POSTROUTING -s 172.22.0.0/24 ! -o br-64ecaf807e64 -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 ! -o br-0f283adad81f -j MASQUERADE
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

所有容器地址均需要进行伪装,才可以将数据传出去

[root@server1 ~]# docker ps  ##查看当前容器共有3个
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
1c4834e8777a        nginx               "nginx -g 'daemon of…"   23 minutes ago      Up 23 minutes       80/tcp              jolly_leakey
32b018ee1ea7        ubuntu              "/bin/bash"              35 minutes ago      Up 35 minutes                           vm1
abbf190aca8c        nginx               "nginx -g 'daemon of…"   39 minutes ago      Up 21 minutes       80/tcp              blissful_robinson
[root@server1 ~]# brctl show  ##当前三个容器均桥接到docker0上
bridge name	bridge id		STP enabled	interfaces
br-0f283adad81f		8000.024250685ac8	no		
br-64ecaf807e64		8000.02424cef9619	no		
docker0		8000.0242c447dc14	no		veth5a5ea00
							veth7857d82
							vetha38d4bb

以容器vm1为例

[root@server1 ~]# docker container attach vm1  ##进入容器vm1
root@32b018ee1ea7:/# 
root@32b018ee1ea7:/# ping www.baidu.com  ##可以与外网进行通信,即容器ip伪装成功
PING www.a.shifen.com (220.181.38.149) 56(84) bytes of data.
64 bytes from 220.181.38.149: icmp_seq=1 ttl=49 time=25.3 ms
64 bytes from 220.181.38.149: icmp_seq=2 ttl=49 time=22.6 ms
^C
--- www.a.shifen.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms

2.端口映射实现外网通信
-p:指定映射端口

[root@server1 ~]# docker run -d --name vm2 -p 80:80 nginx  ##创建容器并端口映射为80
c48bfc53f3eae09ae06276b63d855087e559fd45aaa7a2b979b9edacaf87a032
[root@server1 ~]# docker inspect vm2  ##查看新容器的信息,其中分配ip为172.17.0.3
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",
[root@server1 ~]# docker ps -a  ##查看端口映射是否成功
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                          PORTS                NAMES
c48bfc53f3ea        nginx               "nginx -g 'daemon of…"   About a minute ago   Up About a minute               0.0.0.0:80->80/tcp   vm2
32b018ee1ea7        ubuntu              "/bin/bash"              44 minutes ago       Exited (0) About a minute ago                        vm1
[root@server1 ~]# docker port vm2
80/tcp -> 0.0.0.0:80
[root@server1 ~]# netstat -antlp  ##查看80端口是否暴露出去
tcp6       0      0 :::80                   :::*                    LISTEN      14416/docker-proxy  ##开启docker-proxy进程
tcp6       0      0 :::22                   :::*                    LISTEN      650/sshd            
tcp6       0      0 ::1:25                  :::*                    LISTEN      885/master  
[root@server1 ~]# iptables -t nat -nL  ##查看nat策略,进行了地址转换
Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
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.3:80        
[root@server1 ~]# iptables -t nat -S
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.3:80

当外网访问容器vm2时时,首先容器通过火墙nat规则,将172.17.0.3:80端口暴露出去,并与宿主机80端口连接;则外网访问宿主机80端口时,会连接到容器
测试:
(1)宿主机访问容器

[root@server1 ~]# curl localhost:80

Welcome to nginx!

(2)浏览器端访问宿主机80端口
http://172.25.4.111:80
Docker网络--容器通信_第2张图片
访问成功

[root@server1 ~]# ps ax |grep docker-proxy  ##容器每进行一次端口映射,均会开启一个docker-proxy进程
14416 ?        Sl     0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.3 -container-port 80
14567 pts/1    R+     0:00 grep --color=auto docker-proxy

当宿主机访问本机容器时,使用iptables DNAT策略
当外网访问容器或容器之间进行访问时,使用docker-proxy策略

你可能感兴趣的:(Docker网络--容器通信)