docker高级网络配置
#说明: 当docker启动时,会自动在宿主机上创建一个docker0虚拟网桥,实际上是linux的一个bridge,可理解为一个软件交换机,它会在挂载到它的网口之间进行转发
#ip address |grep docker
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
17: veth4967b39@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
19: veth183c4ca@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
21: vethc0abe5c@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
同时docker随机分配一个本地未占用的私有网络中的一个地址给docker0接口,如上图中的172.17.0.1,掩码16位,之后启动的容器内的网口也会自动分配一个网段的地址
当创建一个容器时,同时会创建一个veth pair接口(当数据发送到一个接口时,另一个接口也会接收相同的数据包),这对接口一个在容器内 即eth0,另一端在本地并被挂载到docker0网桥,名称以veth开头,通过这种方式,主机可以跟容器通信,容器之间也可以通信. docker就创建了在主机和所有容器之间的一个虚拟共享网络。
1、快速配置
只有在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服务启动时指定会成为默认值,后面执行容器启动时可覆盖设置的默认值。
--dns=IP_ADDRESS... #指定特定的DNS服务器
--dns-search=DOMAIN... #指定dns搜索域
只在容器启动时使用,针对容器的特性内容:
-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 #映射容器所有端口到宿主主机
2、配置DNS
在容器中使用mount命令可以看到挂载信息里有三个相关的配置文件,这样可以让宿主机的dns信息发生变更后,容器的dns可以立刻得到更新
/dev/mapper/centos-root on /etc/resolv.conf type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/centos-root on /etc/hostname type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/centos-root on /etc/hosts type xfs (rw,relatime,attr2,inode64,noquota)
如想手动指定容器的配置,进入容器后可使用下面的选项
root@29e314e74d71:/# cat /etc/hostname
29e314e74d71
root@29e314e74d71:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 29e314e74d71
--link=CONTAINER_NAME_NAME:ALIAS
#创建容器时使用上面的选项,可添加一个其它的容器主机名至/etc/hosts文件中,让新创建的容器可使用ALIAS就可连接另一个容器
--dns=IP_ADDRESS
#创建容器时添加dns服务器到容器/etc/resolv.conf中.
--dns-search=DOMAIN
#创建容器时设定容器的 搜索域
***当创建容器时没有指定上面选项时,docker会默认用宿主机上的配置来给容器
3、容器访问控制
#容器想访问外部网络,需本地系统转发开启支持
sysctl net.ipv4.ip_forward #为1支持,为0为没开启转发
sysctl -w net.ipv4.ip_forward=1
docker run --rm --name mycentos1 -it centos /bin/bash
ping baidu.com #测试能否访问外部网络
#永久开启为以下
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
容器之间访问
#需两个条件支持
a、容器之间的网络已经互联,默认所有的容器会连接到docker0网桥上
b、本地系统的iptables是否允许
默认情况,容器之间是互通的
访问所有的端口
容器服务启动时,iptables会自动添加一个转发策略,策略是通过还是禁止取决于配置--icc=true/false,如手动指定--iptables=false,则不会添加iptables规则
默认不同容器之间是网络互通的,如为安全考虑要禁止,可更改/etc/default/docker配置DOCKER_OPTS=--icc=false
容器访问外部网络
容器所有到外部网络的连接,源地址都会nat到本地宿主机系统的ip地址,iptables nat规则有源地址伪装操作
# iptables -t nat -nL
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
外部网络访问容器
当容器启动时-p或-P,会在iptables nat表中添加相应的规则转行相应端口的转发
iptables -t nat -nL
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:32768 to:172.17.0.2:80
DNAT tcp -- 0.0.0.0/0 127.0.0.1 tcp dpt:8080 to:172.17.0.3:80
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8081 to:172.17.0.4:80
4、配置docker0网桥
docker服务默认会创建一个docker0网桥,它在内核层连通了其它物理网卡和虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络当中。
docker0接口的ip和子网会默认指定一个,并且定义了MTU,这些值都可以在服务器启动时进行配置
--bip=CIDR #--ip地址加掩码格式,如 172.17.0.1/16
--mtu=BYTES #覆盖默认的mtu配置
yum -y install bridge-utils #安装包才有brctl
brctl show #查看网桥和端口信息
每次创建新容器时,docker会从可用的地址段中分一个给容器的eth0端口,使用本地主机上docker0接口作为所有容器的默认网关
docker run -it --rm --name mycent1 centos /bin/bash
ip add
#inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
ip route
#default via 172.17.0.1 dev eth0
5、自定义网桥
除了默认docker0网桥,也可以启动服务时使用 -b BRIDGE或--bridge=BRIDGE来指定使用网桥来连接各个容器
5.1、创建网桥
systemctl stop docker #停止docker服务
ip link set dev docker0 down #停止docker0网桥
brctl delbr docker0 #删除docker0网桥
brctl addbr br0 #新建bridge0网桥
ip addr add 192.168.3.1/24 dev br0 #绑定ip给br0网桥
ip link set dev br0 up #启动br0网桥
brctl show 查看网桥信息
yum -y install net-tools #安装ifconfig命令
ifconfig br0 #查看br0网桥信息
5.2、配置docker服务
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H unix:// $DOCKER_OPTS #在ExecStart末尾添加 $DOCKER_OPTS
EnvironmentFile=-/etc/default/docker #指定配置文件的路径
vim /etc/default/docker
DOCKER_OPTS="-b=br0"
systemctl start docker #启动docker服务
docker run --rm -ti --name mycent2 centos /bin/bash #创建一个容器
ifconfig #查看容器ip,检查是否桥接在br0上
ping qq.com #测试网络及到网桥是否通
---------如果容器没有ifconfig和ping命令--------------
在容器中执行以下命令,获取命令相关的包安装
apt-get update
apt install net-tools
apt install iputils-ping
-----------------------------------------------------
6、创建一个点到点的连接
默认所有容器会连接到docker0的虚拟子网中
如需两个容器之间可以不通过宿主机网桥进行连接,创建一对peer接口,放入两个容器中,配置成点对点链路类型
6.1、两个终端启动两个容器
docker run -it --rm --name mytest1 --net=none centos /bin/bash
docker run -it --rm --name mytest2 --net=none centos /bin/bash
6.2、(在第三个终端操作)找到进程号,创建网络命名空间的跟踪文件
docker inspect -f '{{.State.Pid}}' mytest1
18192
docker inspect -f '{{.State.Pid}}' mytest2
18311
mkdir -p /var/run/netns
ln -s /proc/18192/ns/net /var/run/netns/18192
ln -s /proc/18311/ns/net /var/run/netns/18311
6.3、创建一对peer接口,然后配置路由---同样在第三个终端操作
ip link add A type veth peer name B
ip link set A netns 18192
ip netns exec 18192 ip addr add 10.1.1.1/32 dev A
ip netns exec 18192 ip link set A up
ip netns exec 18192 ip route add 10.1.1.2/32 dev A
ip link set B netns 18311
ip netns exec 18311 ip addr add 10.1.1.2/32 dev B
ip netns exec 18311 ip link set B up
ip netns exec 18311 ip route add 10.1.1.1/32 dev B
6.4、测试两容器通信
mytest1上测试
#ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.098 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.076 ms
mytest2上测试
ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.084 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=0.058 ms