docker的高级网络功能主要是对docker启动时默认的网络进行一些定制化的配置,本篇就看看docker官方都介绍了哪些关于网络的高级特性。
当docker启动的时候,它会自动在docker宿主机上创建一个名为docker0的虚拟网桥接口,并且从私网地址网段中随机的选择一段宿主机没有使用的地址,然后把该地址分配到docker0,我的宿主机是192.168.1.0/24网段,所以在docker服务启动后,docker0被分配了172.17.42.1/16网段。
但是docker0网桥接口不是一个普通的接口,他是一个虚拟以太网桥接接口,只要它连接了一些网络,它便可以在这些网络接口之间自动的转发数据包,这样可以使容器和docker主机进行交互。当docker服务创建一个容器的时候,它会创建一对同样的管道(peer)接口,就像管道的两端一样,数据包被送到管道的一端,然后数据包会被自动传输到管道的另一端,这个管道(peer)的一端在容器里面变成eth0接口,然后保持管道的另一端挂接在docker宿主机上,并赋予在宿主机上管道这一端一个名字,名称就像veth*这样,在docker主机的命名空间,然后绑定veth*接口到docker0网桥上,docker0网桥是docker创建的虚拟接口,用来在docker主机和容器进行通讯的接口。
1 这里有一些docker在命令行的一些选项,一些关于网络设置的选项可以提供给docker程序,这样在docker启动的时候,这些特别设置的网络配置就能自动生效。
1 以下命令只能提供给docker服务程序,而且不能在运行过程中动态改变:
-b bridge_name,容器使用网桥的名称,默认是docker0 --bip=CIDR 设置容器使用的网桥的ip网段。ip/mask --fixed-cidr=CIDR 在设置的网段中选择一个更严格的ip范围,类似子网划分,范围必须是ipv4格式和网桥的子网 -H SOCKET 这个命令看起来像用来影响容器的网络配置,但他的作用其实是告诉docker服务在哪个socket上接受命令,比如运行、停止一些容器 --icc=true|false --ip=ipaddress 设置容器的ip地址 --ip-forward=true|false 设置容器可以和外部通讯 --iptables=true|false --mtu=BYTES
2 以下两个参数既可以提供给docker服务程序,也可以在启动一个容器的时候使用,比如docker run:
--dns=ipaddress 在容器的/etc/resolv.conf文件设置dns服务地址,当在/etc/hosts文件中找不到主机名,则会在该ip的53端口进行域名解析 --dns-search=domain 设置domain域名
3 以下的参数只能在运行docker run时使用,因为他们设置的信息都是针对单个容器的:
-h hostname 设置容器的主机名,他会被写入/etc/hostname,/etc/hosts文件里面则是容器名和ip地址的映射,但是容器的主机名在容器外部看不见,它并不会通过docker ps显示出来 --link=contain_name 在使用run命令的时候,可以使用该参数给容器一个新的别名,然后指向该容器的ip地址,这可以使在容器内部的进程在连接容器时并不需要直到该容器的ip地址,因为docker在重启之后会被分配不同的ip地址,使用别名则不需要注意这个问题 -net=bridge|none|host|contain:name or id -p SPEC -P
2 配置DNS
docker如何给每一个容器提供主机名和dns的?不必在构建镜像的时候指定容器的主机名?其实诀窍是覆盖容器内部三个在/etc目录下的文件:hostname、hosts、resolv.conf,你可以在容器内部运行mount命令看看,容器内部和docker宿主机之间共享了一些目录,这种配置允许docker做一些聪明的操作,例如保持和宿主机一样的resolv.conf到所有的容器上面。有四个不同的参数可以影响容器的DNS服务:-h hostname、--link=contain_name、--dns、--dns-search
3 docker容器如何和外部通讯
决定容器和外部世界进行通讯的一个重要因素是docker宿主机是否开启了数据包转发,这个取决于系统中的ip_forward设置,如果该参数设置为1,则数据包可以在容器之间传输,有时候数据包需要离开docker宿主机,这时候你需要设置--ip-forward=true,docker会自动设置ip_forward为1。如果不想让docker自动设置,也可以手动设置:echo 1 > /proc/sys/net/ipv4/ip_forward
4 两个容器之间如何通讯
怎样管理两个容器之间的通讯,在系统层面取决于两点:
1 网络拓扑是否连接到容器的网络接口上,默认情况下docker会自动连接所有的容器到一个docker0网桥上面,提供了一个传输数据包的途径
2 iptables防火墙是否允许进行连接,docker默认不会改变你本机的防火墙规则,如果你设置了--iptables=false,则docker将会在iptable规则中添加forward规则。
5 绑定容器的端口到宿主机上面
默认docker容器可以和外部世界进行连接,但是外部世界却不能连接docker容器,每一个出去的连接都是通过宿主机的iptables masq规则实现的,但是如果你想容器接受来自外部世界的连接,你需要在启动容器时提供一些特定的参数,主要有两个参数:
1 首先,你可以提供-P参数(--publish-all=true|false)在运行docker run的时候,它会把在Dockerfile中通过EXPOSE指定的端口映射到docker主机上的49153-65535端口上,这有点小不方便
2 更方便的是-p SPEC(--publish=SPEC),该参数可以允许你更精确的设置哪个端口映射到docker主机上,可以使任何端口,并不局限在49153-65535
docker默认把端口映射到0.0.0.0地址上面,如果你想限制更多一些,在使用-p时,可以-p IP:host_port:container_port这样来限制。
6 定制docker0网桥
默认情况下,docker服务在启动时自动创建docker0网桥,用docker0在物理机网卡和虚拟网卡之间传输数据包,docker给docker0配置了ip地址、掩码、以及一个ip段地址,docker主机可以通过docker0网桥来发送和接受容器的数据包。可以通过以下参数调整这些默认配置:--bip、--fixed-cidr、--mtu,在ubuntu系统上可在/etc/default/docker配置文件中的DOCKER_OPTS选项中添加以上的参数,这样以便在docker服务启动时配置就自动生效。
如果你运行了多个docker容器,你可以使用brctl命令查看docker0网桥,就可以看到连接在docker0上面的虚拟接口,每次你创建一个新的容器的时候,docker0网桥都会被用到,docker从定义的ip段中选择一个空闲的ip,桥接到网桥上面,然后配置容器的eth0网卡使用该ip,docker主机自己的ip地址在网桥上作为每个容器的默认网关来使用,注意docker主机默认不允许容器发送数据包到外部,除非docker主机开启了包转发功能ip_forward。
7 建立你自己的网桥
如果你不想docker服务构建它自己默认的docker0网桥,你可以在docker启动时设置自己的网桥,使用-b或者--bridge参数来告诉docker服务使用你的网桥来代替默认的网桥,即使你已经启动了docker服务,也可以更改docker0的配置:
#停止docker服务,删除docker0网桥 service docker stop ip link set dev docker0 down brctl delbr docker0 #创建bridge0网桥,并做网桥初始化 brctl addbr bridge0 ip addr add 192.168.5.1/24 dev bridge0 ip link set dev bridge0 up #设置docker服务使用bridge0网桥,并启动docker服务 echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker service docker start
现在docker服务启动后就开始使用你自己定制的网桥bridge0了,然后创建一个新的容器,就会发现新的容器已经使用新网桥的ip段了。
8 docker服务怎样连接容器
docker使用一个特别的虚拟网卡使容器和宿主机进行通讯,一对虚拟接口被称为'peers',它的一端连接宿主机,一端连接着容器,这样就可以在容器和宿主机之间传输数据包了。一般创建docker容器的网络经过以下几个步骤:
1 创建一对虚拟接口 2 在宿主机端,给虚拟接口的一端命名为类似veth65f9这样的名称,并把它绑定到docker宿主机的docker0网桥上面 3 然后把虚拟接口的另一端绑定到创建的容器内部的eth0接口上 4 从网桥上面的地址段中给容器的eth0接口分配一个ip地址,并设置该ip地址的默认网关为docker宿主机的网桥
经过以上几步之后,容器就可以和其他容器或者外部世界进行通讯了。你可以使用--net参数给一个特定的容器执行以上步骤中的某一步骤,--net有以下参数:bridge、host、container:name_or_id、none。这里主要说说none这个配置,none参数告诉docker容器内部有自己的网络栈,但是不进行任何配置,由你在后面进行配置。
9 构建点到点的连接
默认情况下,docker会把所有的容器都连接到虚拟的docker0网桥上面,你可以创建容器让他们连接到不同的虚拟网桥上面。但是有时候你希望两个特定的容器可以直接通讯,而不用增加复杂的绑定配置,这个很好解决,你可以创建一对虚拟接口,然后把该虚拟接口的两端分别放入容器中,然后配置他们就像点对点连接一样。
10 一些小工具
1 pipework是一个shell脚本,它可以帮组你在一个复杂的网络拓普中把容器连接在一起
2 weaver创建了一个虚拟网络,用来连接部署在多台机器上的docker容器
以上只是对官文大概的了解,详细内容请看:network configure