当 Docker 启动时,会自动在宿主机上创建一个 docker0 虚拟网桥,实际上是Linux 的一个 bridge。
Docker 随机分配一个本地未占用的私有网络(在RFC1918中定义)中的一个地址给 docker0接口。比如典型的 172.17.0.1,掩码为255.255.0.0。
此后启动的容器内的网口也会自动分配一个网段(172.17.0.0/16)的地址。
当创建一个 Docker 容器的时候,同时会创建一个 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以接收相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到docker0 网桥,名称以veth 开头(例如 veth4c45933)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间的一个虚拟共享网络。
Docker 网络相关的命令
只有在Docker 服务启动的时候才能配置,而且不能马上生效的有: -b BRIDGE or --bridge=BRIDGE --指定容器挂载的网桥 --bip=CIDR --定制docker0的掩码 -H SOCKET... or --host=SOCKET... --Docker服务端接收命令的通道 --icc=true|false --是否支持容器之间进行通信 --ip-forward=true|false --请看下文容器之间的通信 --iptables=true|false --是否允许Docker添加iptables规则 --mtu=BYTES --容器网络中的MTU 既可以在启动服务时指定,也可以 Docker容器启动(docker run)时候指定。在Docker 服务启动的时候指定则会成为默认值,后面执行 docker run 时可以覆盖设置的默认值: --dns=IP_ADDRESS... --使用指定的DNS服务器 --dns-search=DOMAIN... --指定DNS搜索域 只有在 docker run 执行时使用,因为它是针对容器的特性内容: -h HOSTNAME or --hostname=HOSTNAME --配置容器主机名 --link=CONTAINER_NAME:ALIAS --添加到另一个容器的连接 --net=bridge|none|container:NAME_or_ID|host --配置容器的桥接模式 -p SPEC or --publish=SPEC --映射容器端口到宿主主机 -P or --publish-all=true|false --映射容器所有端口到宿主主机
自定义网桥
除了默认的 docker0 网桥,也可以指定网桥来连接各个容器
在启动Docker 服务的时候, 使用 -b BRIDGE 或 --bridge=BRIDGE 来指定使用的网桥
1)添加网桥
[root@server ~]# systemctl stop docker #停止docker服务 [root@server ~]# ip link set dev docker0 down #停止docker0网桥 [root@server ~]# brctl delbr docker0 #删除docker0网桥 [root@server ~]# brctl addbr bridge0 #新建bridge0网桥 [root@server ~]# ip addr add 192.168.2.1/24 dev bridge0 #绑定ip给bridge0网桥 [root@server ~]# ip link set dev bridge0 up #启动bridge0网桥 [root@server ~]# brctl show #查看网桥信息 bridge name bridge id STP enabled interfaces bridge0 8000.000000000000 no virbr0 8000.525400caf93e yes virbr0-nic [root@server ~]# ifconfig bridge0 #查看bridge0网桥信息 bridge0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.2.1 netmask 255.255.255.0 broadcast 0.0.0.0
2)配置docker服务
[root@server ~]# vim /lib/systemd/system/docker.service #由于新版本的没有/etc/default/docker配置文件,so 需要自己添加。 ExecStart=/usr/bin/dockerd -H unix:// $DOCKER_OPTS #在ExecStart末尾添加 $DOCKER_OPTS EnvironmentFile=-/etc/default/docker #指定配置文件的路径 [root@server ~]# vim /etc/default/docker #自定义编辑配置文件,写入启动指定网桥的网桥信息 DOCKER_OPTS="-b=bridge0" [root@server ~]# systemctl start docker #启动docker服务 [root@server ~]# docker run --rm -ti --name Mycentos centos /bin/bash #创建一个容器 [root@0a13bd05faae /]# ifconfig #查看容器的ip地址,检查是否桥接到birdge0上面 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.2.2 netmask 255.255.255.0 broadcast 192.168.2.255 [root@0a13bd05faae /]# ping 192.168.2.1 #测试和网桥是否通
创建点vs点的连接
默认情况下,Docker 会将所有的容器连接到由 docker0 提供的虚拟子网中。如果我们需要两个容器之间可以通信,而不通过宿主机网桥进行桥接。
解决办法:创建一对 peer 接口,分别放到两个容器中,配置成点对点链路类型即可。
1)启动容器
[root@server ~]# docker run -i -t --rm --name myCentos01 --net=none centos /bin/bash #在第一个终端启动第一个容器
[root@server ~]# docker run -i -t --rm --name myCentos02 --net=none centos /bin/bash #在第二个终端启动第二个容器
2)找到进程号,然后创建网络命名空间的跟踪文件(在第三个终端操作)
[root@server ~]# docker inspect -f '{{.State.Pid}}' myCentos01 #找到myCentos01的进程号 16614 [root@server ~]# docker inspect -f '{{.State.Pid}}' myCentos02 #找到myCentos02的进程号 16713 [root@server ~]# mkdir -p /var/run/netns [root@server ~]# ln -s /proc/16614/ns/net /var/run/netns/16614 [root@server ~]# ln -s /proc/16713/ns/net /var/run/netns/16713
3)创建一对 peer 接口,然后配置路由(在第三个终端操作)
[root@server ~]# ip link add A type veth peer name B [root@server ~]# [root@server ~]# ip link set A netns 16614 [root@server ~]# ip netns exec 16614 ip addr add 10.1.1.1/32 dev A [root@server ~]# ip netns exec 16614 ip link set A up [root@server ~]# ip netns exec 16614 ip route add 10.1.1.2/32 dev A [root@server ~]# [root@server ~]# ip link set B netns 16713 [root@server ~]# ip netns exec 16713 ip addr add 10.1.1.2/32 dev B [root@server ~]# ip netns exec 16713 ip link set B up [root@server ~]# ip netns exec 16713 ip route add 10.1.1.1/32 dev B
4)分别进入连个容器内进行ping测试。