图来源:http://www.slideshare.net/janghoonsim/docker-container-and-lightweight-virtualization
Docker的四种网络模式
bridge 模式,使用 --net=bridge 指定,默认设置。
host 模式,使用 --net=host 指定。
container 模式,使用 --net=container:NAMEorID 指定。
none 模式,使用 --net=none 指定。
Bridge模式
默认模式,容器和宿主机桥docker0连接,docker0在docker安装时自动产生。
一般 Docker 会使用 172.17.0.0/16 这个网段,docker0的IP地址可以在宿主机ifconfig docker0查看。
不加--net参数,启动一个后台驻留的centos7容器,查看一下容器内自动创建的eth0网卡,IP地址与宿主机docker0网卡在同一网段。
docker run -d --name xj_centos1 centos /usr/sbin/init
Host模式
使用--net=host模式启动容器,将不会获得一个独立的 Network Namespace,而是和宿主机共用。容器内不会虚拟出自己的网卡,配置自己的 IP 等。
docker run -d --name xj_centos2 --net=host centos /usr/sbin/init
从shell提示符看起来,和在宿主机的前缀是一样的,但是事实上此时命令是在容器内执行的,运行docker ps会报错,ifconfig的输出和宿主机一样。
Container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
docker run -d --name xj_centos3 --net=container:xj_centos1 centos /usr/sbin/init
在xj_centos1和xj_centos3两个容器内,查看/etc/hostname、ifconfig -a是一样的,但是ps -ef可以看出运行的进程是不同的。
None模式
在这种模式下,Docker 容器拥有自己的 Network Namespace,但是,并不为 Docker容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。
docker run -d --name xj_centos4 --net=none centos /usr/sbin/init
此容器内没有IP配置,而且连网卡都没有,该如何配置--net=none参数启动的容器网络呢,步骤如下:
1、先确认该容器在宿主机上的PID
docker inspect xj_centos4 | grep Pid
2、创建软链接:(ip-netns的man page中建议/var/run/netns/$Pid作为namespace的管理对象)
mkdir -p /var/run/netns
ln -s /proc/29855/ns/net /var/run/netns/29855
3、创建一对虚拟网卡A和B,其中A加入到docker0网桥,并启动,另一个B放入容器内。
ip link add A type veth peer name B /* 创建一对虚拟网卡A和B
brctl addif docker0 A /* 将虚拟网卡A加入到网桥docker0,需提前安装bridge-utils
ip link set A up /*启动网卡A
ip link set B netns 29855 /* 网卡B放入该容器对应的namespace
4、配置容器内的网卡B的设置
ip netns exec 29855 ip link set dev B name eth0 /* 容器内网卡名称重命名为eth0
ip netns exec 29855 ip link set eth0 up /* 启动eth0
ip netns exec 29855 ip addr add 172.17.0.100/16 dev eth0 /* eth0的IP设置为172.17.0.100/16,与docker0的IP地址172.17.0.1同网段即可
ip netns exec 29855 ip route add default via 172.17.0.1 /* eth0网卡的默认网关指向docker0的IP 172.17.0.1
检验配置结果:
容器配置固定IP
如果不做额外设置,容器每次启动都是临时分配与网桥docker0同网段的IP,偶尔也希望能分配一个固定IP,步骤如下:
1、新建一个自定义的network:
docker network create --subnet 192.168.10.0/24 --gateway 192.168.10.254 Net_19216810
docker network ls查看结果,已新增网络"Net_19216810"
宿主机上运行ifconfig -a可以发现多了一个网桥br_05c76f963623,IP地址为192.168.10.254
2、启动容器,指定桥接到新网段,并指定IP地址。
docker run -d --name xj_centos5 --net Net_19216810 --ip 192.168.10.100 centos init
此后停掉此容器再启动,IP依旧是192.168.10.100。
补充一句,正式用途中,毕竟容器的设计和用途与虚拟机不同,容器讲究的是轻量,随需启动,可抛弃性,不建议长久化运行,所以在网络配置上,更多的利用宿主机的网络做映射即可,一般不会有太多的需求去修改容器内的设置,包括网络。
容器内网络配置到本地网络环境中
Docker 自身的网络功能比较简单,不能满足很多复杂的应用场景。因此,有很多开源项目用来改善 Docker 的网络功能,如 pipework 、 weave 、 flannel 等
接下来实验如何使用pipework将 Docker 容器配置到和宿主机同一网段。大致过程是配置一个IP地址与宿主机所在网络同网段的网桥,然后宿主机网卡与 Docker 容器内网卡都连接至此网桥。
我的环境,宿主机IP是 10.9.41.112,网关为 10.9.41.254, 需要给 Docker 容器的地址配置为 10.9.41.150/24。
宿主机上操作步骤如下:
1、安装pipework
git clone https://github.com/jpetazzo/pipework
cp ~/pipework/pipework /usr/local/bin/
2、创建网桥br0,并配置IP和默认网关。
brctl addbr br0
ifconfig br0 up
ip addr del 10.9.41.112/24 dev ens18
ip addr add 10.9.41.112/24 dev br0
ip route del default
ip route add default via 10.9.41.254 dev br0
3、启动无网络的容器,然后使用pipework命令配置容器网络,桥接至br0
docker run -d --name xj_centos6 --net='none' centos /usr/sbin/init
pipework br0 xj_centos6 10.9.41.150/24@10.9.41.254
4、验证配置
docker exec -it xj_centos6 /bin/bash
ifconfig -a