Docker的网络类型及容器之间的访问方式
Docker的网络类型及容器之间的访问方式
Docker安装时会自动的在Docker host上创建三种网络,我们可以使用docker network ls查看。这 三种网络分别是none网络、host网络、bridge网络,bridge网络是我们在创建容器时默认使用的网络。
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
9cb8177d0a4a bridge bridge local
ff99ed99d67b harbor_harbor bridge local
ecf73b7c090a host host local
a8755bdfb429 none null local
None
none网络就是没有网络,可以通过–network=none指定使用none网络,使用none网络时,只有一个lo口。
none网络是个封闭的网络,使用了这种网络类型的容器无法在网络层被访问。封闭意味着隔离,一些对安全性要求高并且不需要 联网的应用可以使用none网络。比如某个容器的唯一用途是生成随机密码,就可以放到none网络中避免密码被窃取。
Host
使用host网络的容器共享Docker host的网络栈,容器的网络配置与Docker host完全一样。可以通过–network=host指定使用 host网络。可以通过以下示例看到,创建容器指定容器网络为host时,容器直接共享了Docker host的网络,能够获取到Docker host 的网络信息。
[root@docker ~]# docker pull busybox #下载busybox用于测试
[root@docker ~]# docker run --name xie -it --rm --network=host busybox:latest
/ # 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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:9a:72:9a brd ff:ff:ff:ff:ff:ff
inet 192.168.100.10/24 brd 192.168.100.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::6dde:7fb9:b3da:5f30/64 scope link noprefixroute
# 直接使用Docker host的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择host网络。当然不便之处就
是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host上已经使用的端口就不能再用了。
Bridge
Docker安装时会创建一个命名为docker0的linux bridge。如果不指定–network,创建的容器默认 都会挂到docker0上。如下示例,docker0上没有任何其他网络设备
[root@docker ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242b3ea18b5 no
virbr0 8000.5254002f8b5d yes virbr0-nic
开启多个终端进行操作
[root@docker ~]# docker run --name xie -it --rm busybox:latest
/ # 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
6: eth0@if7: <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 brd 172.17.255.255 scope global eth0
[root@docker ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242b3ea18b5 no veth608ad4b
virbr0 8000.5254002f8b5d yes virbr0-nic
当我们使用默认网络bridge时,一个新的网络接口被挂到了docker0上,veth608ad4b就是新创建容器的虚拟网卡
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:b3:ea:18:b5 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:b3ff:feea:18b5/64 scope link
valid_lft forever preferred_lft forever
7: veth608ad4b@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 72:d3:f4:f9:38:f2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::70d3:f4ff:fef9:38f2/64 scope link
valid_lft forever preferred_lft forever
在容器创建时,如果使用默认网络,则会从docker0中随机分配ip给容器使用
自定义bridge
通过bridge驱动创建类似默认bridge的网络,当容器需要ip时,可以自动分配ip给容器,也可以加上–ip手动分配,但这个ip必须是地址池里的
[root@docker ~]# docker network create --driver bridge --subnet 192.168.0.0/24 --gateway 192.168.0.254 kami
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
843d308971fc bridge bridge local
ecf73b7c090a host host local
023449708dbd kami bridge local
a8755bdfb429 none null local
[root@docker ~]# docker run -it --name box --rm --network=kami 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
9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:c0:a8:00:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
手动分配
[root@docker ~]# docker run -it --name box --rm --ip 192.168.0.111 --network=kami 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
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:c0:a8:00:6f brd ff:ff:ff:ff:ff:ff
inet 192.168.0.111/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
创建一个默认bridge网络的容器,再创建使用kami的网络的容器,这两个容器之间是不能直接通讯的,只有指定了相同的网络的容器才能够互通,如果想要通讯,可以使用connect参数添加默认网络
[root@docker ~]# docker network connect bridge box
[root@docker ~]# docker run -it --name box --rm --ip 192.168.0.111 --network=kami 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
15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:c0:a8:00:6f brd ff:ff:ff:ff:ff:ff
inet 192.168.0.111/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
17: eth1@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth1
valid_lft forever preferred_lft forever
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.075 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.065 ms
总结:
docker网络的类型有3种
- bridge(桥接网络):默认的网络模式。当Docker启动时,会自动创建一个名为docker0的虚拟网桥,并分配一个子网。除非指定其他网络,否则启动的容器会自动连接到这个桥接网络。容器之间可以通过IP地址通信,也可以通过容器名称通信(使用用户自定义的网络时)。
- host(主机网络):容器不会虚拟出自己的网卡,也不会分配IP,而是使用宿主机的IP和端口。这种模式可以让容器直接使用宿主机的网络接口,从而性能更好,但会牺牲一定的隔离性。
- none(无网络):容器有自己独立的网络栈,但不做任何网络配置,即没有网络接口、IP、路由等信息。需要用户自己手动配置。
docker容器之间的访问方式
容器之间访问可以使用以下方式
1、基于IP地址进行访问
2、基于容器名进行访问
3、多个容器共享同一个网络协议栈
注意:只有在同一个Docker网络中的容器才能够互相通讯;只有使用了默认的Bridge网络的容器是
无法使用基于容器名的方式进行容器互访的。
基于ip地址进行访问
[root@docker ~]# docker run --name xie -it --rm busybox:latest
/ # ip a
19: eth0@if20: <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 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@docker ~]# docker run -it --name box --rm busybox
/ # ip a
21: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.111 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.064 ms
在同一个网络中的容器,是可以互相访问的
基于容器名进行访问
通过IP访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署应用之前可能无法确定IP,部署之后再 指定要访问的IP会比较麻烦。对于这个问题,可以通过Docker自带的DNS服务解决。
从Docker 1.10版本开始,Docker daemon实现了一个内嵌的DNS server,使容器可以直接通过“容器名通信。方法很简单,只要在启动时用–name为容器命名就可以了
/ # ping box
ping: bad address 'box'
如果使用默认的bridge网络,不能用容器名进行访问
[root@docker ~]# docker run --name xie -it --rm --network=kami busybox:latest
/ # ip a
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:c0:a8:00:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
[root@docker ~]# docker run -it --name box --rm --network=kami busybox
/ # ip a
25: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:c0:a8:00:02 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.2/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
直接ping容器名进行测试
/ # ping box
PING box (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: seq=0 ttl=64 time=0.062 ms
64 bytes from 192.168.0.2: seq=1 ttl=64 time=0.066 ms
64 bytes from 192.168.0.2: seq=2 ttl=64 time=0.060 ms
有的容器不能查看ip,直接ping容器名既能知道是否能够通讯,还能知道对方的ip地址
创建容器时,使用–name定义容器名称,当容器启动时,Docker daemon会把容器名与容 器获取的IP进行绑定,写入到Docker DNS中,这样容器之间访问就可以基于容器名实现了,如果容器停止了,该容器 所对应的DNS信息就会从Docker DNS中删除。使用Docker DNS有个限制,只能在新创建的bridge网络中使用。
joined容器
Joined(联合)容器是另一种实现容器间通信的方式。joined容器非常特别,它可以使两个或多个容器 共享一个网络栈,共享网卡和配置信息,joined容器之间可以通过127.0.0.1直接通信。
使用joined容器的方式实现容器间的通讯,需要注意的是两个容器之间的应用端口容易发生冲突, 两个容器共享一个网络栈,那么容器中的应用在运行时,绑定的IP也是一样。
[root@docker ~]# docker exec -it xie /bin/sh
/ # 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
27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:c0:a8:00:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
[root@docker ~]# docker run -it --name box --rm --network=container:xie 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
27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:c0:a8:00:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
两个容器的ip相同共享一个网络栈,可能会发生端口冲突
容器访问外部
1、 容器int_1发送Ping报文包:192.168.0.1 > www.baidu.com。
2、docker0收到报文,发现是发送到外网的,交给NAT处理。
3、NAT将源地址换成ens36的IP:192.168.100.10 > www.baidu.com。
4、Ping包从ens36发送出去,到达 www.baidu.com。
通过 NAT,docker 实现了容器对外网的访问。
如果是虚拟机,则需要进行两次nat的转换,如果是真实的服务器,则只需要进行一次的nat转换
外部访问容器
如果想实现外部访问容器,可使用host网络,容器共享Docker host网络栈,就可以实现外部访问容器。还可以使用端口映射,这也是最常用的方法
更多推荐


所有评论(0)