Docker 网络
一、前言
Docker容器是一个具有隔离性的虚拟系统,容器内可以有自己独立的网络空间,容器与容器之间相互隔离,通过Docker网络进行相互通信。
二、理解 Docker0
1.查看宿主机网卡
ip addr # 查看所有网卡
2.利用 Tomcat 进行测试
docker run -d -P --name tomcat01 tomcat # 运行 tomcat 镜像生成tomcat01容器 tomcat精简版镜像安装ip addr、ping命令 docker exec -it tomcat apt update docker exec -it tomcat apt install -y iproute2 # 安装 ip addr docker exec -it tomcat apt install -y iputils-ping # 安装 ping docker exec -it tomcat01 ip a # 查看容器网卡信息
3.测试宿主机能不能 ping 通 tomcat 容器
ping 172.17.0.2
宿主机可以 ping 通容器内部
4.再次查看宿主机网卡信息,发现多出一个142,刚好和 tomcat01 容器网卡141 相对应。
ip addr
5.在启动一个 tomcat 容器测试,发现又多了一对网卡。
docker run -d -P --name tomcat02 tomcat
ip addr # 再次查看宿主机网卡信息
docker exec -it tomcat02 ip a # 查看 tomcat02 网卡信息(提前安装 iproute2 、iputils-ping)
我们发现这些容器带来的网卡,都是一对一对的。
evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连。
正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备。
OpenStac、Docker 容器之间的连接,OVS的连接,都是使用 evth-pair 技术。
说明:
我们每启动一个 Docker 容器,Docker就会给对应容器分配一个ip,我们只要装了Docker,就会有一个 docker0网卡。
桥接模式,使用的技术是evth-pair技术!
6.测试 tomcat01 和 tomcat02 是否可以 ping 通
docker exec -it tomcat02 ping 172.17.0.2
结论:容器和容器之间是可以相互 ping 通的!
小结
Docker 使用的是Liunx的桥接,宿主机中是一个Docker容器的网桥 docker0。Docker 中所有的网络接口的是虚拟的,虚拟的转发效率高,只要容器删除,对应的一对网桥就没了。
三、--link
思考一个场景,我们编写了一个微服务,database url=ip:,容器重启数据库ip换掉了,我们希望可以处理这个问题,可以通过名字进行访问容器!
1.测试容器名与容器名之间是否可以ping通。
docker exec -it tomcat01 ping tomcat02 # 容器名 ping 容器名是 ping 不通的
2.创建tomcat03容器,通过--link与tomcat02互通。
docker run -it -d -P --name tomcat03 --link tomcat02 tomcat
反向 tomcat02 并不能 ping 通 tomcat03
3.探究:
docker network ls
inspect
docker network inspect 28a59baffff2
tomcat03上绑定了tomcat02
docker exec -it tomcat03 cat /etc/hosts
--link 就是在hosts配置中增加ip与容器名的绑定。
我们现在不建议使用 --link了!推荐自定义网络!
四、自定义网络
docker0 特点:默认 域名不能访问, --link可以打通连接!我们可以自定义一个网络!
1.查看所有的 Docker 网络
docker network ls
2.网络模式
bridge:桥接 docker (默认,自己创建也与使用bridge模式)
none:不配置网络
host:和宿主机共享网络
container:容器内网络联通!(用的少,局限性大)
3.自定义网络
直接启动命令默认是加了 --net bridge ,而这个就是我们的docker0 docker run -d -P --name tomcat01 tomcat docker run -d -P --name tomcat01 --net bridge tomcat
创建自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet # --driver bridge # --subnet 192.168.0.0/16 # --gateway 192.168.0.1
docker network inspect mynet
4.使用tomcat测试
(1)启动两个容器
docker run -d -P --name tomcat-net-01 --net mynet tomcat docker run -d -P --name tomcat-net-02 --net mynet tomcat
(2)查看mynet
docker network inspect mynet
(3)测试 tomcat-net-01 与 tomcat-net-02 的连通性
docker exec -it tomcat-net-01 ping 192.168.0.3 # tomcat-net-01 ping tomcat-net-02 容器ip docker exec -it tomcat-net-01 ping tomcat-net-02 # 容器名与容器名相互 ping
自定义的网络 docker 都已经帮我们维护好了对应的关系,推荐平时自己创建网络进行使用!
好处:
Redis、MySQL 不同的集群使用不同的网络,保证集群是安全健康的!
五、网络连通
1.创建新 tomcat 容器与 tomcat-net-01互通
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 tomcat
docker exec -it tomcat01 ping tomcat-net-01
2.测试打通 tomcat01 - mynet
连通之后就是将 tomcat01 放到了 mynet 网络下,一个容器两个ip!
docker network connect mynet tomcat01
docker exec -it tomcat01 ping tomcat-net-01
结论:要跨网络操作,需要使用 docker network connect 连通!
六、实战:部署Redis集群
1.创建 redis 网卡
docker network create redis --subnet 172.38.0.0/16
2.通过简本创建六个 redis 配置
for port in $(seq 1 6); \ do \ mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat << EOF >/mydata/redis/node-${port}/conf/redis.conf port 6379 bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 172.38.0.1${port} cluster-announce-port 6379 cluster-announce-bus-port 16379 appendonly yes EOF done
3.启动 redis
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \ -v /mydata/redis/node-1/data:/data \ -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6372:6379 -p 16372:16379 --name redis-2 \ -v /mydata/redis/node-2/data:/data \ -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6373:6379 -p 16373:16379 --name redis-3 \ -v /mydata/redis/node-3/data:/data \ -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6374:6379 -p 16374:16379 --name redis-4 \ -v /mydata/redis/node-4/data:/data \ -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6375:6379 -p 16375:16379 --name redis-5 \ -v /mydata/redis/node-5/data:/data \ -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker run -p 6376:6379 -p 16376:16379 --name redis-6 \ -v /mydata/redis/node-6/data:/data \ -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
4.创建集群
docker exec -it redis-1 /bin/sh
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
5.测试
redis-cli -c cluster info cluster nodes set a b
宿主机上停掉 redis-3
docker stop redis-3
get a # redis-1 容器内
cluster nodes # redis-1 容器内
6.高可用 Redis 集群搭建完成!