Docker 网络管理
网络模式
容器网络访问原理
桥接宿主机网络和配置固定IP地址
Docker 支持五种网络模式:
1、网络模式: --net
1.1 bridge
默认网络,Docker启动后默认创建一个docker0网桥,默认创建的容器也是添加到这个网桥中
1.2 host
容器不会获得一个独立的network namespace,而是和宿主机共用一个,使用方法 --net host,这个一般用的比较小,这种情况下,比如说我们容器启用了80的端口,其实也就是占用了宿主机的80端口
1.3 none
获取独立的network namespace,但不为容器进行任何网络配置,进去没有eth0网络,但是有独立的网络空间
1.4 container
和指定的容器使用同一个network namespace,网卡配置也是相同的,(多个容器可以指定共用一个网络)
1.5 自定义
自定义网桥,默认和bridge网络一样
bridge:
[root@node02 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE c8f4ff0091d8 bridge bridge local 88e3f6329cf3 host host local 173e62eaa733 lnmp bridge local b6d9db4c6d31 none null local [root@node02 ~]# docker inspect lnmp [ { "Name": "lnmp", "Id": "173e62eaa733c8783e1d6ee0cb4e65afab7b4469d0eb36a034ccd43e84650da7", "Created": "2018-09-10T18:12:55.98358342+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "306965c1bd589f8f6fe754280b5daeb724153fac8137837c9328acdfacad7cda": { "Name": "lnmp_web", "EndpointID": "bdddc0a754cb30c1c3d7fa512dfb3f620daee665c8ce19fd2a9ab433443aaccb", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" }, "91bba818c0e5d246794d66898e33e5947d6995302f428128dd83e97989781635": { "Name": "lnmp_mysql", "EndpointID": "db553cf6aa4e294731da08cd7a9754a3183b62faa565d4e72b19c4412d4e98dd", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] [root@node02 ~]# ifconfig br-173e62eaa733: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:9bff:fe5d:dd78 prefixlen 64 scopeid 0x20<link> ether 02:42:9b:5d:dd:78 txqueuelen 0 (Ethernet) RX packets 3406918 bytes 299604640 (285.7 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 3406918 bytes 299604640 (285.7 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.30.39.1 netmask 255.255.255.0 broadcast 172.30.39.255 inet6 fe80::42:50ff:fe75:a932 prefixlen 64 scopeid 0x20<link> ether 02:42:50:75:a9:32 txqueuelen 0 (Ethernet) RX packets 52 bytes 5776 (5.6 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 69 bytes 6044 (5.9 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 默认情况下docker的网络方式是bridge,在宿主机会创建一个网桥docker0
Docker 容器的网络的访问原理:
veth 是一个虚拟的网络设备和Docker的eth一对一对应
这里我们装一下查看网桥的工具
yum install -y bridge-utils
bridge show
然后docker0 通过转发和宿主机的eth0进行转发和外部网络通信
容器访问外部
# iptables -t nat -nL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
外部访问容器
# iptables -t nat -nL
Chain DOCKER (2 references)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:88 to:172.18.0.2:80
桥接宿主机网络与配置固定IP地址 临时生效: # 网桥名称 br_name=br0 # 添加网桥 brctl addbr $br_name # 给网桥设置IP ip addr add 192.168.0.211(宿主机IP)/24 dev $br_name # 删除已存在的eth0网卡配置 ip addr del 192.168.0.211/24 dev eth0 # 激活网桥 ip link set $br_name up # 添加eth0到网桥 brctl addif $br_name eth0 # 添加路由 ip route add default via 192.168.0.1 dev br0
执行上面的脚本,br0就具有物理网卡了 还需要在Docker启动时桥接这个网桥: # vi /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -b=br0 # systemctl restart docker 永久生效: # vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 TYPE=Ethernet ONBOOT=yes BRIDGE=br0 # vi /etc/sysconfig/network-scripts/ifcfg-br0 DEVICE=br0 TYPE=Bridge ONBOOT=yes BOOTPROTO=static IPADDR=192.168.0.211 NETMASK=255.255.255.0 GATEWAY=192.168.0.1 DNS1=114.114.114.114
pipework工具配置容器固定IP
git clone https://github.com/jpetazzo/pipework.git
cp pipework/pipework /usr/local/bin/
docker run -itd --net=none --name test01 ubuntu
pipework br0 test01 192.168.0.123/24@192.168.0.1
这个配置过网络之后,容器得到的IP和宿主机是在一个网段的,这个时候可以上外网了。但是这个时候我们要是重启这个容器的话docker restart test01,这个容器的IP就没有了
我们看一下这个脚本
C_ID=$(docker run -itd --net=none ubuntu) C_PID=$(docker inspect -f '{{.State.Pid}}' $C_ID) # 创建network namespace目录并将容器的network namespace软连接到此目录,以便ip netns命令读取 mkdir -p /var/run/netns ln -s /proc/$C_PID/ns/net /var/run/netns/$C_PID # 添加虚拟网卡veth+容器PID,类型是veth pair,名称是vp+容器PID ip link add veth$C_PID type veth peer name vp$C_PID # 添加虚拟网卡到br0网桥 brctl addif br0 veth$C_PID # 激活虚拟网卡 ip link set veth$C_PID up # 设置容器网络信息 IP='192.168.0.123/24' GW='192.168.0.1' # 给进程配置一个network namespace ip link set vp$C_PID netns $C_PID # 在容器进程里面设置网卡信息 ip netns exec $C_PID ip link set dev vp$C_PID name eth0 ip netns exec $C_PID ip link set eth0 up ip netns exec $C_PID ip addr add $IP dev eth0 ip netns exec $C_PID ip route add default via 192.168.1.1
博客总结来源于:http://edu.51cto.com/course/10659.html