容器之間可以通過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。