本章概述
- docker网络类型
- 单机模式下容器之间的互联
- docker跨主机互联之简单实现
- 创建自定义网络
前言
本章主要介绍 docker 网络相关知识。
Docker 服务安装完成之后,默认在每个宿主机会生成一个名称为 docker0 的网卡其 IP 地址都是 172.17.0.1/16,并且会生成三种不能类型的网络,如下图:
查看docker0网卡
查看网络类型:
6.1 docker网络类型
Docker 的网络使用 docker network ls 命令看到有三种类型,下面将介绍每一种类型的具体工作方式:
docker网络类型:
Bridge:#桥接,使用自定义 IP,默认情况下使用的网络模式
Host:#不获取 IP 直接使用物理机 IP,并监听物理机 IP 监听端口
None: #没有网络
6.1.1 Host模式
Host 模式,使用参数 --net=host 指定。
启动的容器如果指定了使用 host 模式,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和 IP 地址,因此在容器里面查看到的 IP 信息就是宿主机的信息,访问容器的时候直接使用宿主机 IP+容器端口即可,不过容器的其他资源包括文件系统、系统进程等还是和宿主机保持隔离。
此模式的网络性能最高,但是各容器之间端口不能相同,适用于运行容器端口比较固定的业务。
1、创建容器
root@docker_server01:~# docker run -d -it --net=host nginx:v1
注意:使用hosts模式创建容器时,由于使用宿主机的网络,将不能再进行端口映射
2、进入容器查看网卡信息,和宿主机一样
查看宿主机网卡信息
host模式容器在创建时,如果指定端口映射,会出现以下报错信息:
6.1.2 none模式
None 模式,使用参数 --net=none 指定
在使用 none 模式后,Docker 容器不会进行任何网络配置,其没有网卡、没有 IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置 IP 等,所以极少使用。
1、创建容器
root@docker_server01:~# docker run -d -it --net=none nginx:v1 bash
2、查看容器网卡信息,没有任何网卡信息
6.1.3 Container 模式
Container 模式,使用参数 --net=container:名称或 ID 指定。
使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网,新创建的容器不会创建自己的网卡也不会配置自己的 IP,而是和一个已经存在的被指定的容器东西 IP 和端口范围,因此这个容器的端口不能和被指定的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过 lo 网卡及容器 IP 进行通信。
1、创建第一个容器,使用bridge模式
root@docker_server01:~# docker run -it -d --name nginx-web1 -p 80:80 --net=bridge nginx:v1
查看容器网卡信息
2、创建container模式的容器,使用第一个容器的网络
root@docker_server01:~# docker run -it -d --name tomcat-web1 --net=container:nginx-web1 tomcat-web:app1
查看容器网卡信息,和创建的nginx-web1的网卡信息一样
6.1.4 bridge模式
Bridge 模式,使用参数 --net=bridge 指定,如果不指定网络模式,默认就是 bridge 模式。
docker 的默认模式即不指定任何模式就是 bridge 模式,也是使用比较多的模式,此模式创建的容器会为每一个容器分配自己的网络 IP 等信息,并将容器连接到一个虚拟网桥与外界通信。
同一台主机上的容器都会连接到docker0这个网桥,并通过docker0进行通信,docker0网桥通过mac地址识别各个容器
1、创建一个容器,不指定网络模式
root@docker_server01:~# docker run -d -it -p 80:80 nginx:v1
2、查看容器的网络模式,默认为bridge模式
docker inspect 容器id
在容器内ping外网,可以正常通外网,这是因为在创建容器时,宿主机上iptables会自动创建一条SNAT规则,自动将容器地址进行源地址转换
查看宿主机iptables规则
6.2 单机模式下容器之间的互联
所谓单机模式,就是指在同一台物理机上。这一章节讲的时在同一台物理机上容器之间的互相访问
6.2.1 通过容器名互联
即在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问,比如一个业务前端静态页面是使用 nginx,动态页面使用的是 tomcat,由于容器在启动的时候其内部 IP 地址是 DHCP 随机分配的,所以如果通过内部访问的话,自定义名称是相对比较固定的,因此比较适用于此场景。
备注:此方式最少需要两个容器之间操作
1、创建第一个tomcat容器,并指定容器名称为tomcat-web1
root@docker_server01:~# docker run -it -d --name tomcat-web1 -p 8801:8080 tomcat-web:app1
进入容器查看hosts
2、创建第二个容器,通--link选项,把第一个容器和第二个容器互联
root@docker_server01:~# docker run -it -d -p 80:80 --name magedu-nginx-web1 --link tomcat-web1 nginx:v1
进入容器查看hosts,可以看到在nginx容器中自动添加了tomcat容器地址和名称解析
3、检测通信,在nginx容器中可以联通tomcat容器
这样就可以在nginx容器中通过容器名称调用tomcat容器
6.2.2 通过自定义容器别名互联
上一步骤中,自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,程序之间也要随之发生变化,比如程序通过容器名称进行服务调用,但是容器名称发生变化之后再使用之前的名称肯定是无法成功调用,每次都进行更改的话又比较麻烦,因此可以使用自定义别名的方式解决,即容器名称可以随意更,只要不更改别名即可,具体如下:
命令格式:
docker run -d --name 新容器名称 --link 目标容器名称:自定义的名称 -p 本地端口:容器端口 镜像名称 shell 命令
注意:目标容器名称是指容器修改后的名称,该名称不固定
自定义的名称是指自己给容器定义的名称,该名称固定,一般不会随意修改
1、启动第三个容器
docker run -it -d -p 81:80 --name magedu-nginx-web2 --link tomcat-web1:java_server nginx:v1
查看容器hosts文件,可以看到在nginx容器中自动添加了tomcat容器别名的和ip地址的解析
3、检测通信,在nginx容器中可以联通tomcat容器
这样只要别名不变,就可以在nginx容器中通过容器名称调用tomcat容器
6.3 docker跨主机互联之简单实现
跨主机互联是说 A 宿主机的容器可以访问 B 主机上的容器,但是6.3前提是保证各宿主机之间的网络是可以相互通信的,然后各容器才可以通过宿主机访问到对方的容器,实现原理是在宿主机做一个网络路由就可以实现 A 宿主机的容器访问 B主机容器的目的,复杂的网络或者大型的网络可以使用 google 开源的 k8s 进行互联。
6.3.1 修改宿主机网段
如果不同主机之间的网段相同,一旦主机之间进行通信,将无法区分是本机网段还是其他主机的网段,因此要先修改不同主机之间的网段,不同主机之间的网段要不相同。
Docker 的默认网段是172.17.0.x/24,而且每个宿主机都是一样的,因此要做路由的前提就是各个主机的网络不能一致
服务器A:eth0网卡地址172.31.7.150,docker0网桥地址修改为10.10.10.1/24
服务器B:eth0网卡地址172.31.7.151,docker0网桥地址修改为10.20.10.1/24
6.3.1.1 更改服务器A网段
1、修改服务器172.31.7.150 docker0网桥的网段
通过在/lib/systemd/system/docker.service 配置文件中添加--bip参数修改
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip 10.10.10.1/24
2、重启docker服务
systemctl daemon-reload && systemctl restart docker
3、验证docker0网卡信息
6.3.1.2 更改服务器B网段
1、修改服务器172.31.7.151 docker0网桥的网段
通过在/lib/systemd/system/docker.service 配置文件中添加--bip参数修改
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip 10.20.10.1/24
2、重启docker服务
systemctl daemon-reload && systemctl restart docker
3、验证docker0网卡信息
6.3.2 两个宿主机分别创建容器
1、在服务器172.31.7.150上创建容器
root@docker_server01:~# docker run -it -p 80:80 nginx:v1 bash
查看容器地址,为10.10.10.2
2、在服务器172.31.7.151上创建容器
查看容器地址,为10.20.10.2
6.3.3 添加静态路由
在各宿主机添加静态路由,网关指向对方的 IP
1、服务器A添加路由
root@docker_server01:~# route add -net 10.20.0.0/24 gw 172.31.7.151
root@docker_server01:~# iptables -A FORWARD -s 172.31.0.0/21 -j ACCEPT
2、服务器B添加路由
root@docker_server02:~# route add -net 10.10.0.0/24 gw 172.31.7.150
root@docker_server02:~# iptables -A FORWARD -s 172.31.0.0/21 -j ACCEPT
6.3.4 容器间通信测试
1、服务器A到服务器B容器联通测试
在服务器172.31.7.150上容器内(地址为10.10.10.2)ping另一台服务器172.31.7.151上容器ip地址(地址10.20.10.2)
2、服务器B到服务器A容器联通测试
6.4 创建自定义网络
可以基于docker命令创建自定义网络,自定义网络可以自定义IP地范围和网关等信息。
6.4.1 创建自定义docker网络
1、创建自定义网络 magedu-net
root@docker_server01:~# docker network create -d bridge --subnet 172.28.0.0/24 --gateway 172.28.0.1 magedu-net
2、查看创建的网络
查看网络详细信息
查看网卡信息
查看网桥
6.4.2 创建不同网络的容器测试通信
1、使用自定义网络创建容器
docker run -it -d -p 8080:8080 --name magedu-net-test --net=magedu-net tomcat-web:app1
进入容器查看网卡信息,测试可以ping通外网
2、创建默认网络的容器
root@docker_server01:~# docker run -it -d -p 8081:8080 --name magedu-net-bridge --net=bridge tomcat-web:app1
查看网卡信息,测试可以通外网
6.4.3 使自定义网络和默认网络容器通信
此时,自定义网络下的容器无法和默认网络通信,这是因为iptables规则拒绝转发自定义网络容器的网卡转发的流量,如下图所示
在自定义网络ping默认网络容器地址,不通
查看iptables规则
要想使自定义网络容器联通默认网络,需要将这两条转发规则删除
1、将iptables规则保存下来
root@docker_server01:~# iptables-save > iptables-backup.log
2、修改iptables规则
vim iptables-backup.log #将如下两条iptables规则注释即可
#-A DOCKER-ISOLATION-STAGE-2 -o br-ddd49d94a0ac -j DROP
#-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
3、重新导入iptables规则
root@docker_server01:~# iptables-restore < iptables-backup.log
4、进入自定义网络容器测试和默认网络容器的连通性
文章评论