自学内容网 自学内容网

docker网络

docker网络

Docker安装时会自动的在Docker host上创建三种网络,我们可以使用docker network ls查看。这 三种网络分别是none网络、host网络、bridge网络,bridge网络是我们在创建容器时默认使用的网络

[root@node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
794128dd47c4   bridge    bridge    local
b0bf0ec21aa8   host      host      local
a8d37488b915   none      null      local
[root@node1 ~]# 

 none网络

故名思议,none网络就是什么都没有的网络。在这个网络下的容器除了lo,没有其他任何网卡。容器创建时,可以通过-- network=none指定使用none网络,通过下面这个示例可以看出,创建容器时指定容器网络类型为none时,容器内只有一个lo网络。

[root@docker ~]# docker pull busybox
[root@docker ~]# docker run --name cygalaxy -it --rm --network=none 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 foreve

none网络是个封闭的网络,使用了这种网络类型的容器无法在网络层被访问。封闭意味着隔离,一些对安全性要求高并且不需要 联网的应用可以使用none网络。比如某个容器的唯一用途是生成随机密码,就可以放到none网络中避免密码被窃取。

host网络

 使用host网络的容器共享Docker host的网络栈,容器的网络配置与Docker host完全一样。可以通过--network=host指定使用 host网络。可以通过以下示例看到,创建容器指定容器网络为host时,容器直接共享了Docker host的网络,能够获取到Docker host 的网络信息。

[root@docker ~]# docker run --name cygalaxy -it --rm --network=host busybox:latest
/ # ip a
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:d4:97:23 brd ff:ff:ff:ff:ff:ff
inet 172.25.0.100/16 brd 172.25.255.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::a246:4804:35d4:bb91/64 scope link noprefixroute
valid_lft forever preferred_lft forever

直接使用Docker host的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择host网络。当然不便之处就 是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host上已经使用的端口就不能再用了。


这次我们使用httpd镜像创建容器,如下示例,可以看出容器中的80端口已经绑定到Docker host的 网络上,如果Docker host自身也有80端口的应用,那么就会与容器的80产生冲突。

[root@docker ~]# docker run --name httpd -itd --network=host httpd
a3dbbf169f8f2c68792658c75bf7d5c0c096a382214fcb881b547ef944167184
[root@docker ~]# ss -tpln | grep 80
LISTEN 0 128 :::80 :::* users:(("httpd",pid=10632,fd=4)...

Bridge网络

Docker安装时会创建一个命名为docker0的linux bridge。如果不指定--network,创建的容器默认 都会挂到docker0上。如下示例,docker0上没有任何其他网络设备。

[root@docker ~]# yum install bridge-utils
[root@docker ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02425f2ee17b no
virbr0 8000.5254008d8bec yes virbr0-nic

我们新创建一个容器,一个新的网络接口veth98c678e被挂到了docker0上,veth98c678e就是新创建容器的虚 拟网卡。由于在创建容器的时候使用了--rm参数,退出容器时会自动的删除容器,需要开启多个终端进行示例操作。

[root@docker ~]# docker run --name cygalaxy -it --rm busybox
/ # ip a
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
valid_lft forever preferred_lft forever

容器有一个网卡eth0@if7。实际上eth0@if7和veth98c678e是一对veth pair。veth pair是一种成对出现的特殊网络 设备,可以把它们想象成由一根虚拟网线连接起来的一对网卡,网卡的一头(eth0@if7)在容器中,另一头 (veth98c678e)挂在网桥 docker0 上,其效果就是将eth0@if7也挂在了 docker0 上


我们还看到eth0@if7已经配置了IP:172.17.0.2,让我们通过docker network inspect bridge看一下 bridge网络的配置信息:

[root@docker ~]# docker network inspect bridge
...... 
"Config": [
{ "Subnet": "172.17.0.0/16", 
    "Gateway": "172.17.0.1"
.........

原来bridge网络配置的subnet就是172.17.0.0/16,并且网关是172.17.0.1。容器创建时,Docker会 自动从172.17.0.0/16中分配一个IP,这里16位的掩码保证有足够多的IP可以供容器使用。

 自定义bridge网络

之前我们所使用的网络都是安装Docker时默认生成的网络。我们可通过bridge驱动创建类似前面默认的 bridge 网络,示例如下,网络名称为cygalaxy123,类型为bridge,地址池为172.19.0.0/16,网关为172.19.0.1。

[root@docker ~]# docker network create --driver bridge --subnet 172.19.0.0/16 --gateway 172.19.0.1
cygalaxy123
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
7db6a96072e6 cygalaxy123 bridge local
[root@docker ~]# ip a
8: br-7db6a96072e6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
group default
link/ether 02:42:af:17:3b:7b brd ff:ff:ff:ff:ff:ff
inet 172.19.0.1/16 brd 172.19.255.255 scope global br-7db6a96072e6
valid_lft forever preferred_lft forever

创建新的容器,指定使用cygalaxy123网络,还可以使用--ip指定容器所使用的ip,这个ip要是 cygalaxy123地址池中的ip。如果不指定ip,那么cygalaxy123会自动给容器分配ip。

[root@docker ~]# docker run --name galaxycy -it --rm --network=cygalaxy123 --ip
172.19.0.100 busybox
/ # ip a
9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:13:00:64 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.100/16 brd 172.19.255.255 scope global eth0
valid_lft forever preferred_lft foreve

如果创建一个容器a1,使用的默认bridge网络,再创建第二个容器a2,使用的cygalaxy123网络,这种情况下两 个容器之间是不能够直接通讯的。只有指定了相同的网络的容器才能够互通。其实我们可以为容器指定多个网络,实现 容器之间的通讯,示例如下,创建新的容器,指定cygalaxy123网络,使用connect参数为该容器添加默认bridge网 络,或者其他的bridge网络。

[root@docker ~]# docker run --name a1 -it --rm busybox
/ # ip a
13: eth0@if14: <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 --name a2 -itd --network=cygalaxy123 --ip 172.19.0.100 busybox
[root@docker ~]# docker network connect bridge a2
[root@docker ~]# docker exec -it a2 sh
/ # ip a
15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:13:00:64 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.100/16 brd 172.19.255.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 foreve

docker容器之间的访问方式 

容器之间访问可以使用以下方式

1、基于IP地址进行访问

2、基于容器名进行访问

3、多个容器共享同一个网络协议栈

注意:只有在同一个Docker网络中的容器才能够互相通讯;只有使用了默认的Bridge网络的容器是 无法使用基于容器名的方式进行容器互访的。

 基于IP地址进行访问

创建一个新的容器mycy_1,使用cygalaxy123网络,容器获取的ip为172.19.0.2

[root@docker ~]# docker run --name mycy_1 -it --rm --network=cygalaxy123 busybox
/ # ip a
19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0

再创建第二个容器mycy_2,使用的也是cygalaxy123网络,直接ping第一个容器mycy_1的IP,示例如下。

[root@docker ~]# docker run --name mycy_2 -it --rm --network=cygalaxy123 busybox
/ # ping 172.19.0.2
PING 172.19.0.2 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.060 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.062 ms

通过以上两个示例得知,在同一个网络中的容器,是可以使用IP进行互相访问的。

基于容器名进行访问

 通过IP访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署应用之前可能无法确定IP,部署之后再 指定要访问的IP会比较麻烦。对于这个问题,可以通过Docker自带的DNS服务解决。

从Docker 1.10版本开始,Docker daemon实现了一个内嵌的DNS server,使容器可以直接通过“容器名”通 信。方法很简单,只要在启动时用--name为容器命名就可以了,示例如下。

[root@docker ~]# docker run --name cy1 -itd --network=cygalaxy123 busybox
[root@docker ~]# docker run --name cy2 -it --network=cygalaxy123 busybox
/ # ping cy1
PING cy1 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.046 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.045 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.051 ms

通过以上示例得知,创建容器时,使用--name定义容器名称,当容器启动时,Docker daemon会把容器名与容 器获取的IP进行绑定,写入到Docker DNS中,这样容器之间访问就可以基于容器名实现了,如果容器停止了,该容器 所对应的DNS信息就会从Docker DNS中删除。使用Docker DNS有个限制,只能在新创建的bridge网络中使用。

joined容器

Joined(联合)容器是另一种实现容器间通信的方式。joined容器非常特别,它可以使两个或多个容器 共享一个网络栈,共享网卡和配置信息,joined容器之间可以通过127.0.0.1直接通信。请看下面的例 子:

[root@docker ~]# docker run --name cy3 -itd --network=cygalaxy123 busybox
[root@docker ~]# docker run --name cy4 -it --rm --network=container:cy3 busybox
/ # ping cy3
PING cy3 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.201 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.039 ms
64 bytes from 172.19.0.3: seq=2 ttl=64 time=0.036 ms

使用joined容器的方式实现容器间的通讯,需要注意的是两个容器之间的应用端口容易发生冲突, 两个容器共享一个网络栈,那么容器中的应用在运行时,绑定的IP也是一样。

容器访问外部

 1、 容器int_1发送Ping报文包:172.17.0.3 > www.baidu.com。

2、docker0收到报文,发现是发送到外网的,交给NAT处理。

3、NAT将源地址换成ens36的IP:192.168.31.106 > www.baidu.com。

4、Ping包从ens36发送出去,到达 www.baidu.com。 通过NAT,docker实现了容器对外网的访问。

外部访问容器

 如果想实现外部访问容器,可使用host网络,容器共享Docker host网络栈,就可以实现外部访问容 器。还有一种方法也是我们最常用的使用端口映射。

Docker可将容器对外提供服务的端口映射到Docker host的某个端口,外网通过该端口访问容器。容 器启动时通过-p参数映射端口,示例如下:

[root@docker ~]# docker run --name web1 -it -d -p 80:80 httpd
4d6f098217e537ff9696801b646c647fa8320c09b68677d1cd59c9977fc9683d
[root@docker ~]# curl http://127.0.0.1:80
<html><body><h1>It works!</h1></body></html>

总结

1.none网络是个封闭的网络,使用了这种网络类型的容器无法在网络层被访问。

2.使用host网络的容器共享Docker host的网络栈,容器的网络配置与host完全一样。

3. 使用Docker默认的bridge网络创建容器,是无法使用容器名进行容器互访的,而使用自定义的bridge 网络创建容器,是可以使用容器名进行容器互访的。

4. 只有在同一个网络下的容器才能够互相访问。 华育智远


原文地址:https://blog.csdn.net/czzwa/article/details/142358899

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!