转载请注明出处: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