当我们完成docker engine的安装以后,docker会在每一个engine上面生成一个3种网络,他们是:bridge
, none
还有host
。
bridge
none
host
多由于独立container之间的通信 首先来侃一侃docker0. 之所以说它是默认的网络,是由于当我们运行container的时候没有“显示”的指定网络时,我们的运行起来的container都会加入到这个“默认” docker0 网络。他的模式是bridge。
安装Docker时,它会自动创建三个网络。您可以使用以下docker network ls
命令列出这些网络:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
557d70cd18ab bridge bridge local
27015fb1d01c host host local
d7bdd36df894 none null local
可以看到,driver
类型为bridge
的网络的名字也为bridge
。在默认情况下,container
都是使用的这个bridge的网络,此时container是可以访问外网和其他container的(需要通过IP地址)。
这三个网络内置于Docker中。运行容器时,可以使用该--network
标志指定容器应连接到的网络。
该bridge
网络是指docker0
存在于所有的码头工人安装网络。除非您使用该docker run --network=<NETWORK>
选项另行指定,否则Docker守护程序默认情况下将容器连接到此网络。您可以使用主机上的ifconfig
命令将此桥接器视为主机网络堆栈的一部分。
$ ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:47:bc:3a:eb
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:17 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1100 (1.1 KB) TX bytes:648 (648.0 B)
默认的名为bridge
的网络是有很多限制的,为此,我们可以自行创建bridge
类型的网络。默认的bridge
网络与自建bridge
网络有以下区别:
-p
参数才能为外界访问,而使用自建的bridge网络时,container的端口可直接被相同网络下的其他container访问。运行以下两个命令以启动两个Ubuntu
容器,每个容器都连接到默认bridge
网络。
$ docker run -itd --name container1 ubuntu
ea30f1c9d86621b54e38b0c890c717b1a56391f0545560b883322edd398c7d98
$ docker run -itd --name container2 ubuntu
ecc3bdf69155dd76955ea2ef7573789ab293ecab61488e5d9c81e589d4395d2b
bridge
启动两个容器后再次检查网络。两个Ubuntu
容器都连接到网络。
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "4784e1934901e6ec7b3575d824904e9022980563aa547059e2e842016e05cf4b",
"Created": "2019-02-15T17:33:24.059683063+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"ea30f1c9d86621b54e38b0c890c717b1a56391f0545560b883322edd398c7d98": {
"Name": "container1",
"EndpointID": "eb8055f5187b1dfa8c17049ca55c53d28c52de6c95ff42d0d23892f0151151f4",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"ecc3bdf69155dd76955ea2ef7573789ab293ecab61488e5d9c81e589d4395d2b": {
"Name": "container2",
"EndpointID": "e0fc810bf1fded3c80a7d89c84bc41a0f83b742f280cab7111002fd266c6ec7c",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
}
}
]
连接到默认bridge
网络的容器可以通过IP地址相互通信。Docker不支持默认网桥上的自动服务发现。如果希望容器能够按容器名称解析IP地址,则应使用用户定义的网络。您可以使用旧版docker run --link
选项将两个容器链接在一起,但在大多数情况下不建议这样做。
顾名思义,所有加入到这个网络模式中的container,都"不能”进行网络通信。貌似有点鸡肋。
直接使用宿主机的网络,端口也使用宿主机的 这种网络模式将container与宿主机的网络相连通,虽然很直接,但是却破获了container的隔离性,因此也比较鸡肋
由于之前介绍的3种自带的网络模式有各自的局限性,因此,docker推荐大家自定义网络。通过自定义网络,我们可以实现“服务发现”与“DNS解析”。
docker 允许我们创建3种类型的自定义网络,bridge
,overlay
,MACVLAN
(目前我还没有用到)。
bridge
:Bridge模式是Docker默认的网络模式,当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,用来连接宿主机和容器,此主机上的Docker容器都会连接到这个虚拟网桥上overlay
:当有多个docker主机时,跨主机的container通信macvlan
:每个container都有一个虚拟的MAC地址Docker Engine本身支持桥接网络和覆盖网络。桥接网络仅限于运行Docker Engine的单个主机。覆盖网络可以包含多个主机,是一个更高级的主题。在本例中,您将创建一个桥接网络:
$ docker network create -d bridge tinywan_bridge
使用
docker network create
创建一个网络 该-d
标志告诉Docker将bridge
驱动程序用于新网络。您可以将此标志保留为此标志bridge
的默认值。继续列出您机器上的网络:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
4784e1934901 bridge bridge local
e8e19c0711e1 host host local
1e8bc1e399a7 none null local
9fd23f7f3998 tinywan_bridge bridge local
要构建协同工作但安全地执行的Web应用程序,请创建网络。根据定义,网络为容器提供完全隔离。首次运行容器时,可以将容器添加到网络中。
启动运行PostgreSQL数据库的容器并将其传递给它--net=my_bridge
以将其连接到新网络:
$ docker run -d --net=tinywan_bridge --name db redis:5.0-alpine
或者使用全名:
docker run -d --network=tinywan_bridge --network-alias db redis:5.0-alpine
通过选项--network-alias
将取名的db
起了一个别名
如果你检查,tinywan_bridge
你会发现它附有一个容器。您还可以检查容器以查看其连接位置:
$ docker inspect --format='{{json .NetworkSettings.Networks}}' db
{
"tinywan_bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"11379ad91a62"
],
"NetworkID": "9fd23f7f3998962d6b378f4cbab8cc9f8a2e7aa64bb3502dd1c0b3a5c1d0c7b0",
"EndpointID": "9c530e400049590b4ba63b75de96c0039b4ee52dbf36fad51df84a24fc028e3e",
"Gateway": "192.168.192.1",
"IPAddress": "192.168.192.2",
"IPPrefixLen": 20,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:c0:a8:c0:02",
"DriverOpts": null
}
}
现在,继续开始您熟悉的Web应用程序。这次不指定网络。
$ docker run -d --name web nginx
您的web
应用程序在哪个网络下运行?检查应用程序,您会发现它正在默认bridge
网络中运行。
{
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "4784e1934901e6ec7b3575d824904e9022980563aa547059e2e842016e05cf4b",
"EndpointID": "4f6372bc7152f73b6ddc13296ce365a024ada4074d19b2aaac8066b1a6f8ca92",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
然后,获取您的IP地址web
容器的
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web
172.17.0.2
现在,打开运行web
容器的shell:
$ docker exec -it web bash
nginx 镜像默认是没有安装
ping
和ipconfig
命令的,这里需要手动安装 1、更新安装包:apt-get update
2、安装网络包:apt-get install tools-net
3、安装ping包:apt-get install iputils-ping
查看 web 容器ip
root@b6b8928824f8:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 2521 bytes 8728256 (8.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2460 bytes 175592 (171.4 KiB)
# ping 192.168.192.2
PING 192.168.192.2 (192.168.192.2) 56(84) bytes of data.
^C
--- 192.168.192.2 ping statistics ---
7 packets transmitted, 0 received, 100% packet loss, time 6046ms
稍后,使用CTRL-C
结束ping
,你会发现ping失败。这是因为两个容器在不同的网络上运行。你可以解决这个问题。然后,使用该exit
命令关闭容器。
Docker网络允许您将容器附加到任意数量的网络。您还可以附加已在运行的容器。继续并将正在运行的web
应用程序附加到tinywan_bridge
。
$ docker network connect tinywan_bridge web
重新获取web
容器的IP地址
$ docker inspect --format='{{range .NetworkSettings.Networks}} {{.IPAddress}}{{end}}' web
172.17.0.2 192.168.192.3
web
再次打开应用程序中的shell并尝试ping命令。这次只使用容器名称db
而不是IP地址。
root@b6b8928824f8:/# ping db
PING db (192.168.192.2) 56(84) bytes of data.
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=2 ttl=64 time=0.105 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=3 ttl=64 time=0.088 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=4 ttl=64 time=0.088 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=5 ttl=64 time=0.084 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=6 ttl=64 time=0.108 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=7 ttl=64 time=0.093 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=8 ttl=64 time=0.088 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=9 ttl=64 time=0.086 ms
^C
--- db ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 7998ms
rtt min/avg/max/mdev = 0.079/0.091/0.108/0.009 ms
的确ping
表明它是接触不同的IP地址,在地址tinywan_bridge
是从其上地址不同bridge
的网络。
当然了,在web
容器中。通过IP地址也会是可以ping同的db
容器的
root@b6b8928824f8:/# ping 192.168.192.2
PING 192.168.192.2 (192.168.192.2) 56(84) bytes of data.
64 bytes from 192.168.192.2: icmp_seq=1 ttl=64 time=0.096 ms
64 bytes from 192.168.192.2: icmp_seq=2 ttl=64 time=0.082 ms
64 bytes from 192.168.192.2: icmp_seq=9 ttl=64 time=0.104 ms
^C
--- 192.168.192.2 ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 7997ms
rtt min/avg/max/mdev = 0.073/0.085/0.104/0.015 ms