layout: post
title: Docker网络
date: 2018-04-21
tags: [“Docker”,”自动化运维工具”]
一、docker网络名称空间原理。
docker的网络与内核的名称空间有关,每一个docker容器彼此之间拥有不同的名称空间,而对于宿主机的TCP/IP协议栈来说,docker容器的网络实际是宿主机TCP/IP协议栈的一部分。docker使用与宿主不同的网络名称空间,通过虚拟网卡来实现与主机进行桥接的。
为了更好的理解docker网络的名称空间,下面我会做网络名称空间的实际例子。
二、netns网络虚拟化
netns是在linux中提供网络虚拟化的一个项目,使用netns网络空间虚拟化可以在本地虚拟化出多个网络环境,目前netns在lxc容器中被用来为容器提供网络,其原理与docker是同样的。
使用netns创建的网络空间独立于当前系统的网络空间,其中的网络设备以及iptables规则等都是独立的,就好像进入了另外一个网络一样。
每一个网卡接口都只能够在一个名称空间中工作,我们可以使用虚拟以太网卡对不同的网络名称空间进行桥接。
下面我们使用”ip”命令来构建一个独立的网络名称空间,并使之与默认的网络名称空间进行通信。
1、环境准备
yum install -y briage-utils
2、使用ip命令创建一个新的网络名称空间
ip help #获取ip命令帮助
ip netns help #获取网络名称空间帮助
ip netns add mynetspace #创建一个新的网络名称空间
ip netns exec mynetspace ifconfig -a #在mynetspace挽留过名称空间中执行命令
lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1 (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
3、创建虚拟网卡
ip link add vethx type veth peer name veth0 #创建一对虚拟网卡(其中vethx与vethy是对等的,就相当于一个虚拟网卡的两部分)
ip link set veth0 netns mynetspace #讲vethy放入 mynetspace 网络名称空间中
ip netns exec mynetspace ifconfig -a
lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1 (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
veth0: flags=4098<BROADCAST,MULTICAST> mtu 1500
ether 02:7e:99:4a:63:19 txqueuelen 1000 (Ethernet)
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
4、将vethx和docker0进行桥接(已经安装了docker)
brctl addif docker0 vethx
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024271e0ef26 no vethx
5、为veth0配置ip地址并ping docker0
ip netns exec mynetspace ifconfig veth0 172.17.0.10/16 up
ip netns exec mynetspace ifconfig lo 172.17.0.10/16 up
ip netns exec mynetspace ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.122 ms
64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.110 ms
64 bytes from 172.17.0.1: icmp_seq=3 ttl=64 time=0.048 ms
^C
--- 172.17.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.048/0.093/0.122/0.033 ms
6、删除虚拟空间
ip netns del mynetspace #删除网络名称空间
注意:这时我们所创建的虚拟以太网卡已经消失了,vethx 和 veth0 是秤和砣的关系,相互依存。
注意:默认的docker的网卡接口一半在容器内,而另一半则关联到了docker0桥上。
三、docker的网络模型
1、封闭式网络模型(容器内只有一个lo设备,不能与其他网络名称空间进行通信)
2、桥接式网络模型,容器内拥有网络接口并桥街道docker0桥(默认,且常用,DNAT)
3、联合式网络模型,多个容器共用同一个网络名称空间,容器与容器之间可以使用lo进行内部通信,从而实现了IPC(只用网络名称空间是共享的,其他的则不共享)
4、开放式网络模型,直接使用宿主机的网络名称空间(例,一个运行着nginx的docker容器,其使用的开放式网络模型,当有请求访问宿主机的80端口,而做出响应的实际是运行nginx的docker容器,使用这种网络模型可以实现快速的分发和启动,但当使用单个应用程序时则不建议使用这种模型,因为容器与宿主机隔离的越彻底越好)
四、docker的4种网络模型实现
使用桥网络运行容器:
docker run -itd --name c1 --rm --network bridge nginx:1.12-alpine
使用无网络运行容器:
docker run -itd --name c2 --rm --network none nginx:1.12-alpine
使用开放式网络运行容器:
docker run -itd --name c3 --rm --network host nginx:1.12-alpine #此种方式运行的容器,容器内的应用所监听的端口会直接在宿主机上进行监听。
使用联合式网络运行容器:
docker run -itd --name c4 --rm --network bridge nginx:1.12-alpine #联合式网络需要使用bridge模型来运行
815b7c86382e81a148de94535135fed1a51144334895aa6d7fa3ba80a61f3d51
docker run -itd --name c5 --rm --network container:c4 tetraweb/php #固定格式, 和名称为c4的容器共用一个网络名称空间
c5592c273c8a79982692c7878d37ba27f3c88b565808a7b492b80f4c4ebdb3e6
五、docker运行与主机端口的映射
-p 选项的使用格式
-p <containerPort> # 将指定的容器端口映射至主机所有地址的一个动态端口
-p <hostPort>:<containerPort> # 将容器端口 <containerPort> 映射至指定的主机端口 <hostPort>
-p <ip>::<containerPort> # 将指定的容器端口 <containerPort> 映射至主机指定 <ip> 的动态端口
-p <ip>:<hostPort>:<containerPort> # 将指定的容器端口 <containerPort> 映射至主机指定 <ip> 的端口 <hostPort>
" 动态端口" 指随机端口,具体的映射结果可使用 docker port 命令查看