Docker(四)网络管理

  • A+
所属分类:Docker

这里首先介绍Bridge模式,Docker会默认创建docker0的网桥,用于NAT转发,我们可以通过以下命令查看。Docker有两种映射方式,一种是随机端口映射,一种是指定端口映射;生产场景一般不使用随机端口映射,但是随机端口映射的好处就是由Docker分配,端口不会冲突,这里通过Nginx镜像来演示Docker的网络管理。

Docker支持四种网络模式

host模式、container模式、none模式、bridge模式

参考:http://www.infoq.com/cn/articles/docker-network-and-pipework-open-source-explanation-practice/

使用默认网桥

注意:确保宿主机内核可以转发IP包,否则容器无法上网,但是不影响NAT端口转发

永久修改网络转发

[root@py ~]# vim /usr/lib/sysctl.d/00-system.conf
net.ipv4.conf.all.forwarding = 1
[root@py ~]# sysctl -p /usr/lib/sysctl.d/00-system.conf

Centos7修改系统默认内核参数配置文件有差异;

临时修改网络转发

[root@py ~]# sysctl net.ipv4.conf.all.forwarding=1
[root@py ~]# sysctl net.ipv4.conf.all.forwarding
net.ipv4.conf.all.forwarding = 1

检查网桥

[root@py ~]# brctl show
bridge name bridge id  STP 
enabled interfaces
docker0  8000.02427d0aee75 no
[root@py ~]# ifconfig 
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.3  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::20c:29ff:fe11:20bf  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:11:20:bf  txqueuelen 0  (Ethernet)
        RX packets 1255849  bytes 668202476 (637.2 MiB)
        RX errors 0  dropped 4  overruns 0  frame 0
        TX packets 188787  bytes 44293224 (42.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:7dff:fe0a:ee75  prefixlen 64  scopeid 0x20<link>
        ether 02:42:7d:0a:ee:75  txqueuelen 0  (Ethernet)
        RX packets 43  bytes 2956 (2.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3  bytes 258 (258.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

检查NAT表

[root@py ~]# iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0           
RETURN     all  --  192.168.122.0/24     224.0.0.0/24        
RETURN     all  --  192.168.122.0/24     255.255.255.255     
MASQUERADE  tcp  --  192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
MASQUERADE  udp  --  192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
MASQUERADE  all  --  192.168.122.0/24    !192.168.122.0/24   
Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0

下载镜像

[root@py ~]# docker pull nginx
[root@py ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/nginx     latest              40960efd7b8f        5 hours ago         108.4 MB

随机端口映射

参数-P(大写),P 就代表着随机映射。

docker run -d -P --name test_nginx nginx

查看映射的随机端口

[root@py ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
01810835aada        nginx               "nginx -g 'daemon off"   3 minutes ago       Up 3 minutes        0.0.0.0:32771->80/tcp   test_nginx

本机32771端口映射到容器80端口,这时候通过浏览器访问本机ip:32771就能看到nginx欢迎页;

指定端口映射

docker run --rm -it -p 81:80 nginx

注意这回的p可是小写哦。这样就可以把物理机的81端口映射到了容器里的80端口。

docker run --rm -it -p 192.168.56.20:81:80 nginx

将192.168.56.20的81端口映射到容器的80端口(默认是0.0.0.0即全部IP),好吧这个需求主要针对宿主机多ip

docker run --rm -it -p 192.168.56.20::80 nginx

将192.168.56.20的随机端口映射到容器的80端口(注意这回可是两个:),至于这个需求主要针对宿主机多ip且需要随机映射端口

docker run --rm -it -p 81:80/tcp nginx

将宿主机的81端口的tcp请求转发到容器的80端口

 docker run --rm -it -p 192.168.56:81:80/tcp nginx

将192.168.56.20的81端口的tcp请求转发到容器的80端口

除了tcp还有udp请求一样可以转发在这里就不一一列举了

Docker 自定义网桥

停止docker服务

systemctl stop docker
systemctl status docker

关闭/删除docker0网桥   

ip link set dev docker0 down
ip link del dev docker0
brctl show

安装网桥工具,创建桥接网卡

[root@lab01 ~]# yum -y install bridge-utils
[root@lab01 ~]# brctl addbr br0

自定义网桥设置(以下是centos 7.2网络桥接配置)

cd /etc/sysconfig/network-scripts/
cp ifcfg-eno16777736 /root/br/ifcfg-eno16777736.bak
cp ifcfg-eno16777736 ifcfg-br0 
[root@py network-scripts]# vim ifcfg-br0 
TYPE="Bridge"
BOOTPROTO="static"
DEFROUTE="yes"
PEERDNS="yes"
PEERROUTES="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_PEERDNS="yes"
IPV6_PEERROUTES="yes"
IPV6_FAILURE_FATAL="no"
STP="yes"
DELAY="0"
NAME="br0"
DEVICE="br0"
IPADDR="192.168.1.3"
PREFIX="255.255.255.0"
GATEWAY="192.168.1.1"
DNS1="202.106.0.20"
ONBOOT="yes"

将本地网卡绑定到br0

[root@py network-scripts]# vim ifcfg-eno16777736 
NAME="eno16777736"
UUID="63858c4f-052a-46d4-86ac-5fe4150b1863"
DEVICE="eno16777736"
ONBOOT="yes"
BRIDGE="br0"

重启网络,并查看网桥状态

[root@py network-scripts]# systemctl restart network
[root@py network-scripts]# brctl show
bridge namebridge idSTP enabledinterfaces
br08000.000c291120bfyeseno16777736

配置 Docker 服务,默认桥接到br0

[root@py ~]# cat /etc/sysconfig/docker-network 
# /etc/sysconfig/docker-network
DOCKER_NETWORK_OPTIONS="-b=br0"

启动docker服务

systemctl daemon-reload
systemctl start docker
systemctl status docker

进入容器,会发现分配一个br0网段的ip

[root@py ~]# docker_in yalei
[root@ea231a2af5a9 /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.1  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::42:c0ff:fea8:101  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c0:a8:01:01  txqueuelen 0  (Ethernet)
        RX packets 17484  bytes 1949567 (1.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 783  bytes 49006 (47.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

注意:192.168.1.1绑定在br0上,只能和宿主机通讯,无法和局域网通讯。

Docker容器配置到本地网络环境中

参考:

http://www.infoq.com/cn/articles/docker-network-and-pipework-open-source-explanation-practice/

http://blog.csdn.net/kongxx/article/details/73477932

http://blog.csdn.net/chinagissoft/article/details/51251982

Docker自身的网络功能比较简单,不能满足很多复杂的应用场景。因此,有很多开源项目用来改善Docker的网络功能,如pipework、weave、flannel等。这里,就先介绍一下pipework的使用和工作原理。

pipework是由Docker的工程师Jérôme Petazzoni开发的一个Docker网络配置工具,由200多行shell实现,方便易用。

pipework工作流程

  • 查看主机是否包含br0(可以自定义)网桥,如果不存在就创建

  • 向容器实例test1添加一块网卡(可以设置网卡名),并配置固定IP:192.168.14.243

  • 若test1已经有默认的路由,则删除掉,将@后面的192.168.14.254设置为默认路由的网关

  • 将test1容器实例连接到创建的br0上

创建容器

[root@py ~]# docker run -d --name test1 --net=none hub.c.163.com/public/centos:7.2-tools  
[root@py ~]# docker run -d --name test2 --net=none hub.c.163.com/public/centos:7.2-tools
[root@py ~]# docker_in test1
[root@f35637f1fb38 /]# ifconfig 
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

禁用默认br0网桥分配的172.17.0.1网段,所以我设置--net=none

安装pipework

宿主机操作,下载安装pipework

cd /root/tools
git clone https://github.com/jpetazzo/pipework
cp pipework/pipework /usr/local/bin/
chmod +x /usr/local/bin/pipework

宿主机操作,为两台容器分别配置ip、子网掩码和网关

[root@py ~]# pipework br0 test2 192.168.1.104/24@192.168.1.1
[root@py ~]# pipework br0 test1 192.168.1.103/24@192.168.1.1

注:格式为ip/子网掩码@网关

测试通讯

因为刚开始我们已经把宿主机eth0绑定到br0,所以宿主机可以分别ping通两台主机;

局域网其他主机也可以ping通;

遗留问题

pipework目前还有缺陷,就是容器重启后IP设置会自动消失,需要重新设置,下面我们再介绍其他更加有效的方法。

pipework设置永久IP

前面已经提到通过使用pipework方式,为容器设置固定IP,但是该方法有一个问题就是如果我们的容器实例重启,设置的固定IP会丢失,这显然回事一件令人头疼的事情,如果我们重启后IP依然保持设置的,岂不是一件很好的事情,接下来我们就介绍一下如何完成这个需求。

脚本下载地址

https://github.com/lioncui/docker-static-ip

Docker(四)网络管理docker-static-ip-master.zip

[root@py ~]# cd /root/tools/
[root@py tools]# git clone  
[root@py ~]# /root/tools/docker-static-ip
[root@py docker-static-ip]# ls
containers.cfg  duration.py  README.md

安装依赖

yum  install python-pip python-dev build-essential
pip install docker-py

停止刚刚创建的容器,容器停止后,会自动释放ip

[root@py docker-static-ip]# docker ps -a
CONTAINER ID        IMAGE                                   COMMAND                  CREATED             STATUS              PORTS               NAMES
96d79ddd4775        hub.c.163.com/public/centos:7.2-tools   "/usr/bin/supervisord"   28 minutes ago      Up 28 minutes                           test2
f35637f1fb38        hub.c.163.com/public/centos:7.2-tools   "/usr/bin/supervisord"   33 minutes ago      Up About a minute                       test1
[root@py docker-static-ip]# docker stop test1
test1
[root@py docker-static-ip]# docker stop test2
test2

将配置信息,写入containers.cfg

[root@py docker-static-ip]# echo "f35637f1fb38,br0,192.168.1.103/24,192.168.1.1" >> containers.cfg
[root@py docker-static-ip]# echo "96d79ddd4775,br0,192.168.1.104/24,192.168.1.1" >> containers.cfg
[root@py docker-static-ip]# cat containers.cfg 
#<container-id>,<bridge-name>,<ipaddress/netmask>,<gateway>
f35637f1fb38,br0,192.168.1.103/24,192.168.1.1
96d79ddd4775,br0,192.168.1.104/24,192.168.1.1

注意:

后续新增容器,只需要修改containers.cfg文件,不需要重新运行脚本;

如果要摘除ip,只需要删除某条配置,重启容器即可;

运行python脚本

[root@py docker-static-ip]# python duration.py

登陆容器测试

[root@py docker-static-ip]# docker_in test1
[root@f35637f1fb38 /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.103  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::806b:a4ff:febb:3455  prefixlen 64  scopeid 0x20<link>
        ether 82:6b:a4:bb:34:55  txqueuelen 1000  (Ethernet)
        RX packets 355  bytes 26695 (26.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 26  bytes 1916 (1.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@f35637f1fb38 /]# exit
logout
[root@py docker-static-ip]# docker_in test2
[root@96d79ddd4775 /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.104  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::185a:5dff:fe84:a7c1  prefixlen 64  scopeid 0x20<link>
        ether 1a:5a:5d:84:a7:c1  txqueuelen 1000  (Ethernet)
        RX packets 404  bytes 34873 (34.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 648 (648.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@96d79ddd4775 /]# ping 192.168.1.103
PING 192.168.1.103 (192.168.1.103) 56(84) bytes of data.
64 bytes from 192.168.1.103: icmp_seq=1 ttl=64 time=0.315 ms
64 bytes from 192.168.1.103: icmp_seq=2 ttl=64 time=0.118 ms
^C
--- 192.168.1.103 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.118/0.216/0.315/0.099 ms
[root@96d79ddd4775 /]# ping 192.168.3.160
PING 192.168.3.160 (192.168.3.160) 56(84) bytes of data.
64 bytes from 192.168.3.160: icmp_seq=1 ttl=63 time=3.76 ms

通过测试,宿主机局域网都能ping通容器,容器重启后ip也不丢失。

YaLei

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: