容器之间可以通过IP,DockerDNSServer或者joined容器三种方式通信。
一、IP的方式
可以参考前面讲到的容器的网络。
二、Docker DNS Server的方式
docker daemon内嵌了一个默认的DNS Server,使容器可以通过“容器名”通信,只需要在启动容器时使用 --name命名就行了,但是这种方式只能适用于自定义网络的容器,使用docker0默认网桥的不行。例如我们刚才启动的nginx1、2和3,都是使用了自定义的网络,我们可以在容器内部使用ping命令直接ping容器名:
root@37773b729b9b:/# ping -c 4 nginx3
PING nginx3 (172.19.0.3) 56(84) bytes of data.
64 bytes from nginx3.mynet2 (172.19.0.3): icmp_seq=1 ttl=64 time=0.081 ms
64 bytes from nginx3.mynet2 (172.19.0.3): icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from nginx3.mynet2 (172.19.0.3): icmp_seq=3 ttl=64 time=0.062 ms
64 bytes from nginx3.mynet2 (172.19.0.3): icmp_seq=4 ttl=64 time=0.057 ms
--- nginx3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.057/0.065/0.081/0.009 ms
如上,使用了自定义网络的容器,可以互相之间直接ping容器名,但使用默认网桥docker0的就不行,比如我们启动两个容器分别为web1和web2,互相ping一下:
[root@docker ~]# docker run --name web1 -P -d docker.io/nginx
927c8a9ebe634e635ebd707a7b9ba2721b96f3057b058d2ae29c2e2b24f11278
[root@docker ~]# docker run --name web2 -P -d docker.io/nginx
e815be1402fb242333fd32a07b3e6604395d80e3c011ed73906642f43d09a704
[root@docker ~]# docker exec -it web1 bash
root@927c8a9ebe63:/# ping -c 4 web2
ping: web2: No address associated with hostname
root@927c8a9ebe63:/#
以上,标黄的地方可以看出,使用docker0默认网桥的容器,使用DNS Server是ping不通的。
三、 joined容器的方式
joined容器可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined容器之间可以使用127.0.0.1通信。
先创建一个nginx容器,名为web1:
[root@docker ~]# docker run --name web1 -P -d docker.io/nginx
68b821dca1e364065bcfefcf068f5e288ce9ef6e08f4650f5be77ecd616fae46
再创建一个busybox容器,并使用–network=container:web1指定joined容器为web1,并查看busybox容器的IP和MAC地址:
[root@docker ~]# docker run -it --network=container:web1 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
34: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
再查看web1容器的IP和MAC:
[root@docker ~]# docker exec -it web1 bash
root@98b1b5be5fd7:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:2 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 2944 bytes 8607213 (8.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2830 bytes 198380 (193.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
由上面标黄处可看出,两个容器的IP和MAC完全一致。
joined容器非常适合以下场景:
不同容器中的程序,希望通过lookback高效快速地通信,比如web server和app server。
希望监控其他容器中的网络流量,比如运行在独立容器中的网络监控程
四、外部网络访问容器
在启动容器时,如果不指定启动参数,外部网络是无法访问容器内部的。当容器中运行一些网络应用,要让外部网络访问这些应用时,可以通过-P或者-p参数来指定端口映射。
(1)-P是随机指定映射端口,后面不需要写上端口号;
(2)-p是手动指定映射端口,后面必须要写上宿主机端口和容器端口。
具体使用方法如:
[root@docker ~]# docker run --name nginx1 -P -d docker.io/nginx
cad6b93f1b9cd6214e5fa16d1f1e812b4ab11b00e137ee48cf38ac195977d666
[root@docker ~]# docker run --name nginx2 -p 8080:80 -d docker.io/nginx
3970f4a12026fb0c29595a531837b46d209fbb42cc99f04af9b8de0f174eca6e
[root@docker ~]#
以上启动了两个容器,我们来看一下两个容器的映射端口:
可以看出nginx1我们使用的-P参数,系统随机指定的宿主机端口是32728,映射到容器的80/tcp端口,我们在外部访问nginx1容器的时候,可以直接访问宿主机IP:32782,;而nginx2容器我们使用的是-p 8080:80参数,手动指定宿主机的80端口映射到容器的80端口,我们在访问nginx2容器的时候,可以直接访问素质及IP:80。