概览
容器网络,为容器之间或容器和非Docker负载之间提供了连接和通信的能力。
一个容器,没有关于其连接网络的信息,或其连接的“同行”是不是Docker工作负载。一个容器只知道一个网络接口和一个IP地址,一个网关,一个路由表,DNS服务以及其他网络信息,除非这个容器使用了none
网络驱动。
本文从容器的视角来描述网络,容器网络的一些概念,不涉及特定操作系统下Docker网络的细节。
端口发布
默认情况下,当你用docker create
或docker run
创建或运行一个容器时,并不向外界暴露任何端口。使用--publish
或-p
标签可使一个容器的端口对外界服务可用,这在主机上创建了一个防火墙规则,将容器的端口映射到Docker主机的端口上,以此暴露给外界。如下是一些例子:
-p 8080:80 | 将容器内的TCP 80端口映射到主机的8080端口 |
---|---|
-p 192.168.1.100:8080:80 | 将容器内的TCP 80端口映射到主机IP 192.168.1.100的8080端口 |
-p 8080:80/udp | 将容器内的UDP 80端口映射到主机的UDP 8080端口 |
-p 8080:80/tcp -p 8080:80/udp | 将容器内的TCP 80端口映射到主机的8080端口,把UDP 80端口映射到主机UDP 8080端口 |
默认情况下,将容器的端口对外暴露是不安全的。意味着,当对外暴露容器的端口时,这个端口不仅对Docker主机可用,同样对外界其他主机可用。
如果对外暴露容器端口时,指定本地IP(127.0.0.1
),则只有Docker主机可以访问该端口
docker run -p 127.0.0.1:8080:80 nginx
如果想让一个容器对其他容器可访问,并不必须把容器端口对外暴露。容器间的通信可以通过将这些容器连接到同一个网络的方式实现,一般使用bridge 网络。
IP地址和主机名
默认情况下,容器从它连接的网络处获取ip地址。容器接收网络的IP子网之外的IP地址,Docker守护进程为容器执行动态子网和IP地址分配。每一个网络也有一个默认的子网掩码和网关。
当你使用docker network connect
,把一个容器连接到一个不同的网络,可以使用--ip
或--ip6
标签指定容器的IP地址。
当一个容器启动时,使用--network
,只能连接到一个网络。使用docker network connect
命令可以将一个运行中的容器连接到多个网络。当使用--network
标签启动一个容器时,可以使用--ip
或--ip6
来指定容器的ip地址。
同样,一个容器的默认主机名是容器的ID,可以使用--hostname
重写主机名。当使用docker network connect
连接一个网络时,可以使用--alias
标签为这个容器在这个网络上指定一个别名。
DNS服务
默认情况下,容器继承宿主机的DNS设置,定义在/etc/resolv.conf
配置文件中。连接到默认bridge
网络的容器接收这个文件的一个拷贝。连接到自定义网络的容器使用Docker的内置DNS服务。内置的DNS服务将外部DNS查找转发到主机上配置的DNS服务。
使用docker run
或docker connect
启动容器时,可以在启动容器的基础上配置DNS解析。下面的表格描述了docker run
的相关DNS配置的标签。
标签 | 说明 |
---|---|
–dns | DNS服务器的ip地址。为了指定多个DNS服务,使用多个--dns 标签。如果容器无法访问指定的IP地址,则使用谷歌的公共DNS服务器8.8.8.8 。这允许容器解析internet域。 |
–dns-search | 用于搜索非完全限定主机名的DNS搜索域。要指定多个DNS搜索域,使用多个--dns-search 标签。 |
–dns-opt | 代表一个DNS选择和其值的键值对。有关有效选项,可参阅操作系统的resolv.conf文件。 |
–hostname | 一个容器的主机名,如果不指定,则默认是主机ID。 |
有IPv6地址的名称服务器
如果宿主机的/etc/resolv.conf
文件含有一个或多个名称服务器条目有IPv6地址,这些名称服务器条目被复制到运行容器中的/etc/resolv.conf
文件中。
对于使用musl-libc(即Alpine Linux)的容器,这将导致主机名查找的竞争条件。因此,如果外部IPv6 DNS服务器赢得了与内置DNS服务器的竞争条件,主机名解析可能偶尔会失败。
外置的DNS服务器比内置的DNS服务器快是很少见的,但是,像垃圾回收或大量并发DNS请求这样的事情,在某些情况下可能会导致外部服务器的往返比本地解析更快。
网络驱动
Docker的网络子系统是可插拔的,使用驱动程序。默认情况下,存在如下几个驱动,提供的网络核心功能:
bridge
:桥接网络,默认网络驱动。如果不指定,则创建这种网络。桥接网络一般被用于同一主机之上多个容器之间的通信。host
:主机网络,消除容器和Docker主机之间的网络隔离,直接使用主机的网络。overlay
:此网络连接多个Docker守护进程,用于Swarm服务,多个节点之间的容器通信。这种策略消除了操作系统层面路由的需要。ipvlan
:此网络驱动为用户提供了对IPv4和IPv6寻址的完全控制。VLAN驱动程序在此基础上构建,使用用户能够完全控制第2层VLAN标记,甚至为对底层网络集成感兴趣的用户提供IPvlan L3路由macvalan
:此网络允许你为容器指定一个MAC地址,使其像一个物理设备出现在网络中。Docker守护进程通过容器的MAC地址将流程路由到容器。当处理希望直接连接到物理网络而不是通过Docker主机的网络堆栈路由的遗留应用程序时,使用macvalan
驱动有时是最佳选择。none
:完全将一个容器和主机及其他容器隔离,在Swarm服务中不可用。- 网络插件:在Docker中也可以安装第三方网络插件。
总结
- 当不需要特殊网络功能时,默认的bridge网络对运行容器已足够。
- 用户自定义bridge网络可以使同一Docker主机上容器相互通信。用户定义的网络通常为属于公共项目或组件的多个容器定义一个隔离的网络。
- host网络分享主机的网络给容器,当使用这个网络驱动时,容器的网络和主机的网络不隔离。
- 当需要不同Docker主机上的容器相互通信,或多个应用使用Swarm服务工作在一起时,overlay网络驱动是最好的选择。
- 当你从虚拟机设置迁移或需要容器看起来像网络上的物理主机时,macvlan网络是最好的,每个都有唯一的一个MAC地址。
- IPvlan网络和Macvlan很像,但并不为容器分配MAC地址。当可以分配给网络接口或端口的MAC地址数量有限时,可以考虑IPvlan。
- 第三方网络插件可使Docker的指定的网络堆栈集成。