转载请注明出处:www.huamo.online
字节杭州 求贤若渴:
本文概述了Docker
默认网络的配置,包含了默认创建的网络类型,以及如何创建你自己的用户定义网络。同时也描述了在一台主机或者在一个集群中创建网络所需要的资源。
如要了解在Linux主机中,Docker
是如何与iptables
进行交互的,可以参看Docker and iptables。
默认网络
当你安装Docker时,它会自动创建3个网络。你可以使用docker network ls
命令罗列出这些网络:
1 | $ docker network ls |
这3个网络內建在Docker
中。当你运行一个container
时,你可以使用--network
标记来指定你的容器要连接哪个网络。
bridge
网络代表了在所有Docker
安装中都存在的docker0
网络。除非你使用docker run --network=<NETWORK>
命令指定了其它网络,Docker后台默认都会将container连接到这个网络。你可以在主机上使用ifconfig
命令看到这个bridge
网络属于主机网络栈的一部分。
1 | $ ifconfig |
none
网络会将容器添加到一个容器特定的(container-specific)网络堆栈中。这种容器会缺少一个网络接口,即Docker不会为这个容器配置任何IP地址,该容器也无法访问外网以及其它容器。它只有一个本地回环地址,通常用来进行批处理工作。如果你进入到这个容器中并查看它的网络堆栈,你会发现验证上面的描述:
1 | $ docker run -it --network=none registry.cn-hangzhou.aliyuncs.com/docker/ubuntu14.04 /bin/bash |
备注:以上的进入方式,可以输入
exit
退出container
host
网络则是将container
添加到主机的网络堆栈中。就网络而言,主机和容器并没有隔离。比如,如果你的容器使用host
网络,在80端口运行了一个web服务器,那么这个服务器就可以在主机的80端口上使用。
none
网络和host
网络在Docker中不能直接配置。但是,你可以配置默认的bridge
网络,你自己定义的网桥网络也可以配置。
默认的bridge
网络
默认的bridge
网络存在于所有的Docker主机上。如果你不指定其它的网络,新的container都会自动连接到这个默认的bridge
网络中。
docker network inspect
命令可以返回一个网络的相关信息:
1 | $ docker network inspect bridge |
运行下面2个命令启动2个busybox
容器,连接到默认的bridge
网络上。
1 | $ docker run -itd --name=container1 busybox |
启动完这2个容器之后,再次查看bridge
网络。2个busybox
容器都已经连接上该网络。记下它们的IP地址,在你的主机上的结果,可能会与下面的例子不同。
1 | $ docker network inspect bridge |
连接到默认bridge
网络的容器,可以通过IP地址相互通信。Docker不支持在默认bridge
网络上自动服务发现。如果你想让容器可以根据容器名字解析出IP地址,你就需要使用用户定义网络而不是默认bridge
网络。你也可以使用旧版的docker run --link
选项将2个容器连接起来,但在大多数情况下不建议这么做。
你可以attach
到一个正在运行的container
中,去从容器内部观察网络情况。因为是以root
身份进入的,所以命令提示符变为了#
。
1 | $ docker attach container1 |
在容器内部,使用ping
命令来测试和其它容器的IP连接情况。
1 | / # ping -w3 172.17.0.3 |
使用cat
命令查看容器的/etc/hosts
文件。这里展示了容器可以识别的主机名和IP地址。
1 | / # cat /etc/hosts |
想要从container1
容器中退出来,并且让它继续保持运行状态,可以使用ctrl+p
,ctrl+q
退出。如果你有兴趣,还可以attach
到container2
中重复如上命令。
默认的docker0
网桥网络支持使用端口映射,搭配上docker run --link
就可以允许容器在docker0
网络中交流。但是不推荐这种做法。如果可能的话,你应该使用下面的用户定义的网桥网络方式来实现。
用户定义的网络
推荐使用用户定义的桥接网络来控制哪些容器可以互相通信,并且以此启用容器名到IP地址的自动DNS解析。Docker提供了默认的网络驱动来创建这些网络。你可以创建一个新的bridge
网络,overlay
网络,MACVLAN
网络。你也可以创建一个网络插件或者远程网络进行完整的个性化和控制。
你可以创建足够多的网络,并且可以让一个容器在任意时刻连接到0个或多个这些网络中。此外,你可以不需要重启容器,就能将运行中的容器连接或者脱离网络。当一个容器连接到了多个网络上,它的外部连接是由第一个非内部网络来提供的,按照词典排序。下面会更详细的描述Docker中每个内置的网络驱动。
bridge
网络驱动
bridge
网络是在Docker中最常用的网络类型。用户创建的bridge
网络类似于默认的bridge
网络,但加上了一些新的特性,并移除掉了一些旧的功能。下面的例子创建了一些bridge
网络,并且让容器在这些网络中执行了一些实验。
1 | $ docker network create --driver bridge isolated_nw |
创建完网络后,你可以使用docker run --network=<NETWORK>
选项将容器连到该网络上。
1 | $ docker run --network=isolated_nw -itd --name=container3 busybox |
你部署在这个网络中的容器必须和该网络处于同一个Docker宿主机上。在该网络中的容器可以直接相互通信。但是,网络本身将这些容器和外部网络隔离开。
在一个用户定义的bridge
网络中,是不支持linking的。你可以在这个网络中的容器上暴露和发布容器端口。这样可以让你从外部网络访问bridge
网络中的部分容器。
bridge
网络对于在单一主机上运行一个规模相对较小的网络是非常适合的。但是,你还可以通过创建overlay
网络来搭建一个更加庞大的网络环境。
docker_gwbridge
网络
docker_gwbridge
是一个本地bridge
网络,在如下2种不同的状况下,会由Docker自动创建出来:
- 当你初始化或者加入一个
swarm
时,Docker会创建出docker_gwbridge
网络,并使用它在swarm
节点的不同机器之间进行通信。 - 当一个容器的所有网络都不能提供外部连接时,Docker会将该容器额外再连接到
docker_gwbridge
网络,以便这个容器可以连接外部网络,或者其它的swarm
节点。
如果你需要一个自定义配置,可以提前创建docker_gwbridge
网络,否则Docker就会按需创建。下面的这个例子使用了一些定制选项来创建docker_gwbridge
网络。
1 | $ docker network create --subnet 172.30.0.0/16 \ |
当你使用overlay
网络时,docker_gwbridge
网络始终存在
在swarm
模式中的overlay
网络
你可以在一个运行swarm
模式的管理者节点上创建一个overlay
网络,并不需要外部的key-value
存储。swarm
使overlay
网络仅用于需要服务的swarm
中的节点。当你创建一个使用overlay
网络的服务时,管理者节点会自动将overlay
网络扩展到运行服务任务的节点上。
想要了解更多关于以swarm
模式运行Docker引擎的知识,可以参看Swarm mode overview。
下面的例子展示了如何在swarm
中的一个管理节点上,创建一个网络,并将它用于一个服务:
1 | $ docker network create \ |
只有swarm
服务才能连接overlay
网络,独立的容器是无法连接的。关于swarm
更多信息,可以看Docker swarm mode overlay network security model 和 Attach services to an overlay network。
无swarm
模式的overlay
网络
如果你没有以swarm
模式运行Docker引擎,那么overlay
网络就需要一个合法的key-value
存储服务。支持的key-value
存储包含Consul
, Etcd
, ZooKeeper (分布式存储)
。在以这种方式创建网络之前,你必须安装和配置好你选中的key-value
存储服务。该Docker的宿主机必须能够联网,并且服务必须能够通信。
以
swarm
模式运行的Docker引擎,不兼容和外部的key-value
存储进行网络连接。
这种使用overlay
网络的方式对于大多数Docker使用者都不推荐。它可以在单一的swarm
集群中使用,或者对那些在Docker之上搭建解决方案的系统开发人员有用处。在未来这种方式可能会被废弃。如果你实在需要通过这种方式使用overlay
网络,看这篇指导文档。
自定义网络插件
如果你需要的东西在上文中都没被提到,那么你可以使用Docker的插件基础设施,编写自己的网络驱动插件。插件会以一个单独的进程运行在执行Docker后台的主机上。使用网络插件是一个高阶话题。
网络插件遵循和其它插件一样的限制和安装规则。所有的插件都使用插件API,并且有一个围绕安装,启动中,停止中,和激活的生命周期。
当你创建并安装了一个自定义的网络驱动后,你就可以创建一个网络,通过--driver
参数使用这个自定义驱动。
1 | $ docker network create --driver weave mynet |
你可以inspect
这个网络,将容器连接上或者脱离开这个网络,甚至移除它。一个特定的插件为了使用可能会有特定的需求依赖。查看插件的文档获取特定的信息。关于编写插件更多内容,可以查看Extending Docker 和 Writing a network driver plugin。
内置的DNS服务器
Docker后台运行了一个内置的DNS服务器,为连接在同样的用户定义网络中的容器之间提供DNS解析服务,以便这些容器能够将容器名解析为IP地址。如果内置的DNS服务器无法解析一个请求,它将会转发给为容器配置的任何一个外部DNS服务器。为了在容器创建时促成这些功能,只有127.0.0.11
可以访问的内置DNS服务器才会被罗列到容器的resolv.conf
文件中。关于用户定义网络中的内置DNS服务器更多信息,可以参看embedded DNS server in user-defined networks。
暴露和发布容器端口
在Docker网络中,有2种不同的,都直接涉及到网络端口的运行机制:暴露和发布端口。这个适用于默认的bridge
网络和用户定义的bridge
网络。
- 在Dockerfile中使用
EXPOSE
关键字,或者在docker run
命令行中使用--expose
参数,你就可以暴露端口。暴露端口是一种描述哪些端口已被使用的方式,但它实际上并没有映射或者打开任何端口。暴露端口是可选的。 - 在Dockerfile中使用
PUBLISH
关键字,或者在docker run
命令行中使用--publish
参数,你就可以发布端口。这会告诉Docker在容器的网络接口中要打开哪些端口。当一个容器端口被发布后,它会被映射到宿主机一个可用的高序端口上(端口号高于30000
),除非你在运行时指定了要映射到宿主机哪个端口上。不能在Dockerfile中指定映射到宿主机哪个端口,因为没有办法可以保证,当你运行这个镜像时,这个指定的主机端口还依然可用。
下面这个例子发布了容器的80
端口,并映射到主机一个随机的高序端口上(在本例中,是32768
)。-d
参数使得容器在后台运行,这样你就可以继续输入docker ps
命令。
1 | $ docker run -it -d -p 80 nginx |
下一个例子指定将容器的80
端口映射到宿主机上的8080
端口。如果8080
端口不可用则将会失败。
1 | $ docker run -it -d -p 8080:80 nginx |
Links
在Docker支持用户定义网络之前,你可以使用Docker的--link
特性来让容器将其它容器的名字解析为IP地址,并且还可以访问被链接的容器的环境变量。如果可能,你应该尽量避免使用这个古老的--link
参数。
当你创建链接时,它会和使用默认bridge
网络或者使用用户定义bridge
网络表现不同。更多信息,可以查看在默认bridge
网络中的Legacy Links,和在用户定义网络中的linking containers in user-defined networks。
Docker和iptables
Linux主机使用一个叫iptables
的内核模块来管理网络设备的访问,包括路由,端口转发,网络地址转换(NAT),和其它相关的操作。Docker会修改iptables
的规则,比如当你启动或停止一个发布端口的容器时,当你创建或修改网络时,当你将容器加入网络时,或者其它网络相关的操作时。
关于iptables
的完整讨论超出了本文范围。随时查看iptables
的规则是行之有效的方法,你可以使用iptables -L
命令进行查看。会罗列出很多列表,你可以只显示一个特定的列表,比如nat
,prerouting
,postrouting
,用类似这样的命令就能做到:iptables -t nat -L
。要查看iptables
的全面文档,可以到netflilter/iptables。
一般情况下,iptables
规则是由一个初始化脚本或者一个譬如firewalld
的守护进程创建。规则在系统重启后会不复存在,所以脚本或者工具必须在系统启动时运行,通常是在运行级别3或者直接是网络初始化完成后运行。也可以查看Linux发行版的对应网络文档,找出合适的方法使得iptables规则持久化。
Docker动态管理iptables
规则用于守护进程,也为容器,服务,网络提供支持。在Docker 17.06以及更高版本
,你可以向一个名叫DOCKER-USER
的新列表添加规则,这些规则将会在Docker自动创建的任何规则之前被加载。如果你需要在Docker运行之前就启用一些iptables
规则,这个正好是你需要的。
参考文章
- https://docs.docker.com/engine/userguide/networking/
- https://stackoverflow.com/questions/41083328/what-is-the-use-of-host-and-none-network-in-docker
转载请注明出处:www.huamo.online