CentOS7-Docker 网络-06
1、理解Docker0
准备工作:清空所有的容器,清空所有的镜像
-- 删除所有容器
docker rm -f $(docker ps -a -q)
-- 删除全部镜像
docker rmi -f $(docker images -qa)
1、测试
1、 查看本地IP
ip addr
-- 本机回环地址
lo 127.0.0.1
-- 虚拟机IP
ens33 192.168.1.102
-- docker网桥
docker0 172.17.0.1
2、运行一个Tomcat容器,并查看它的IP地址
-it 以交互的方式运行容器
-P 随意映射端口号
--name 自定义运行的容器名称
docker run -it -P --name tomcat001 tomcat
-- 进入容器
docker exec -it 容器ID /bin/bash
-- 运行 ip addr,发现报错
ip addr
⭐解决方案
- 主要原因是docker的base镜像只包含简单的操作系统,其他命令需要自己安装;
-- 运行下发命令
apt update && apt install -y iproute2
docker容器内找不到命令,bash: ip: command not found—_小鱼塘
3、宿主机ping容器测试
是可以ping通的
2、原理
- 每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。
- 这是个桥接网卡,使用了veth-pair技术!
1、查看启动容器后,宿主机IP地址情况
- 启动容器前
- 启动容器后
- 多了一个 vethf4a8b0b@if8 的网络!
2、再启动一个容器,看看宿主机的IP地址变化
- 又多了一个 veth305bdaf@if10 的网络
3、我们来测试下tomcat001和tomcat002容器间是否可以互相ping通
- tomcat001:172.17.0.2
- tomcat002:172.17.0.3
docker exec -it tomcat002 ping 172.17.0.2
结论
- 宿主机和容器之间是可以互相访问的。
- 容器和容器之间是可以互相访问的。
3、网络模型图
结论
- tomcat001和tomcat002共用一个路由器。
- 他们使用的一个,就是docker0。
- 任何一个容器启动默认都是docker0网络。
- docker默认会给容器分配一个可用ip。
4、小节
- Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据
- Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。
- 因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接
通信。
- Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);
- Docker中的网络接口默认都是虚拟的接口。
- 虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。
2、–Link(了解)
- 容器与容器之间可以通过IP地址来进行通信
- 若容器内的IP会变化,此时两容器之间的通信就不是很方便了
- 如果可以通过容器名进行通信,那不管容器内的IP是否发生变化,也无关紧要了
1、-- link的使用
1、首先启动两个Tomcat容器
2、我们使用tomcat02,直接通过容器名ping tomcat01,不使用ip
docker exec -it tomcat02 ping tomcat01
3、报错
4、解决方法
1、进入容器内
docker exec -it 容器自定义名称 /bin/bash
2、运行下面命令
apt-get update
3、出现 bash: ping: command not found 报错,运行下方命令
apt install iputils-ping
5、再次使用tomcat02,直接通过容器名ping tomcat01,不使用ip
6、再启动一个tomcat03,但是启动的时候连接tomcat02
-it 以交互方式运行容器
-P 随机映射端口号
--name 自定义运行的容器名称
-- link 网络连接
docker run -it -P --name tomcat03 --link tomcat02 tomcat
7、我们就可以使用tomcat03 ping通tomcat02
docker exec -it tomcat03 ping tomcat02
-- 报错
[root@localhost ~]# docker exec -it tomcat03 ping tomcat02
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ping": executable file not found in $PATH: unknown
-- 进入tomcat03容器,运行下方命令即可
apt-get update
apt install iputils-ping
> -- 验证结果,是可以
8、反之,使用tomcat02 ping通tomcat03
docker exec -it tomcat02 ping tomcat03
-- 反向 使用tomcat02 ping通tomcat03,结果是失败的
9、原因
1、进入容器tomcat03
docker exec -it tomcat03 /bin/bash
2、查看 /etc/hosts文件
3、原因:
--link的时候,直接把需要link的主机的域名和ip直接配置到了hosts文件中了。
3、自定义网络(掌握)
1、基础命令
指令 | 作用 |
docker network 选项 | 用于管理网络 |
- 选项
选项 | 作用 |
connect | 将容器连接到网络 |
create | 创建新的 Docker 网络。默认情况下,在 Windows 上会采用 NAT 驱动,在 Linux 上会采用Bridge 驱动。可以使用 -d 参数指定驱动(网络类型)。 |
disconnect | 断开容器的网络 |
inspect | 提供 Docker 网络的详细配置信息 |
ls | 用于列出运行在本地 Docker 主机上的全部网络 |
prune | 删除 Docker 主机上全部未使用的网络 |
rm | 删除 Docker 主机上指定网络 |
2、查看所有网络
docker network ls
3、所有网路模式
网路模式 | 配置 | 说明 |
bridge模式 | - -net=bridge | 默认值,在Docker网桥docker0上为容器创建新的网络栈 |
none模式 | - -net=none | 不配置网络,用户可以稍后进入容器,自行配置 |
container模式 | - -net=container:name/id | 容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Networknamespace。 |
host模式 | - - net=host | 容器和宿主机共享Network namespace |
用户自定义 | - - net=自定义网络 | 用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络 |
4、查看一个具体的网络的详细信息
-- docker network inspect 网络ID
docker network inspect 4b6feee16f21
[
{
"Name": "bridge",
"Id": "4b6feee16f21d3e08e568205b4399e8e8560950289df5bc2c25f8b3c617f1680",
"Created": "2022-01-10T22:13:08.00841766+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"0d9d2f2399b3ea5a48876654f226da0f8fc5f2ccb12f69967fcc6c6f4ab988be": {
"Name": "tomcat02",
"EndpointID": "fe929b37d61034241a7185f0f33ec36a6ebbcc4e14d29060e9042b22618d3d83",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"f47a5726ee6dce483f26d4d683036d35249d1413bbc38b239805bf46c72d9e28": {
"Name": "tomcat03",
"EndpointID": "51f7206a0f26931359e393b893d514cae0153969017732ecac23dc4805fb415d",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
5、自定义网络
1、删除原来的所有容器
docker rm -f $(docker ps -qa)
2、创建容器,默认创建的容器都是docker0网卡的
-d 后台运行
-P 随机映射端口号
-- net bridge 使用 docker0网卡
docker run -d -P --name tomcat01 --net bridge tomcat
- docker0网络的特点
- 它是默认的
- 域名访问不通
- --link 域名通了,但是删了又不行
3、自定义创建一个网络网络
--driver bridge 使用默认的 bridge(docker0网卡)
--subnet 设置子网掩码
--gateway 设置网关
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 my-network
4、查看自定义网络的源数据
docker network inspect df25cdbe33e2
-- my-network自定义网络源数据
[
{
"Name": "my-network",
"Id": "df25cdbe33e28fb3e2526211e15c997bb23b60ca3f96179a422f4ba5299e03e5",
"Created": "2022-01-10T23:19:26.484474614+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
6、使用自定义网络
1、启动两个容器测试,使用自己的 my-network网络
1、启动第一个容器
-- net 使用自定义网络 my-network
docker run -d -P --name tomcat_my-network01 --net my-network tomcat
2、启动第二个容器
docker run -d -P --name tomcat_my-network02 --net my-network tomcat
2、查看自定义网络 my-network的源数据
docker network inspect df25cdbe33e2
-- my-network的源数据
[
{
"Name": "my-network",
"Id": "df25cdbe33e28fb3e2526211e15c997bb23b60ca3f96179a422f4ba5299e03e5",
"Created": "2022-01-10T23:19:26.484474614+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"6f3d0cc49b71893691b61096d1c5f3b09c1c2b6125addec3f5c472248e587b17": {
"Name": "tomcat_my-network01",
"EndpointID": "94487712aec256a8ef12ebe0edcf8c55aa9563f29c908f76ea11f4c53717b962",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"9807f4930aa08f275e2d05baeb8d9f9683edee8d7f8cb2d23f267706bc52120d": {
"Name": "tomcat_my-network02",
"EndpointID": "9241a50264b6e5a575f0d4112b700397b387e95c4de355986c4ffe956331f1bf",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
7、测试使用自定义网络的容器
1、使用IP测试
docker exec -it tomcat_my-network01 ping 192.168.0.3
2、使用容器自定义名称测试
docker exec -it tomcat_my-network01 ping tomcat_my-network02
4、网络连通
- docker0和自定义网络肯定不通
- 使用自定义网络的好处就是网络隔离
1、让 tomcat_my-network01 访问 tomcat01
1、在docker0网络下, 启动默认的容器
-- tomcat01
docker run -d -P --name tomcat01 tomcat
-- tomcat02
docker run -d -P --name tomcat02 tomcat
2、查看当前的容器
3、使自定义网络 my-network 和 docker0默认网络通信
-- docker network connect 自定义网络 默认网络docker0下启动的Tomcat容器
docker network connect my-network tomcat01
4、查看此时自定义网络 my-network的源数据
docker network inspect my-network
[
{
"Name": "my-network",
"Id": "df25cdbe33e28fb3e2526211e15c997bb23b60ca3f96179a422f4ba5299e03e5",
"Created": "2022-01-10T23:19:26.484474614+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"550024b10f6c29df55f7d992aa9ca8ed15b45eb96b57d4fd0e0102417e89b2d5": {
"Name": "tomcat01",
"EndpointID": "2521d9511dc29a1e765a0f62ecaa5febf204180acbcc82ba178e2882087458b1",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
"6f3d0cc49b71893691b61096d1c5f3b09c1c2b6125addec3f5c472248e587b17": {
"Name": "tomcat_my-network01",
"EndpointID": "94487712aec256a8ef12ebe0edcf8c55aa9563f29c908f76ea11f4c53717b962",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"9807f4930aa08f275e2d05baeb8d9f9683edee8d7f8cb2d23f267706bc52120d": {
"Name": "tomcat_my-network02",
"EndpointID": "9241a50264b6e5a575f0d4112b700397b387e95c4de355986c4ffe956331f1bf",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
可以看到,在默认网络docker0下启动的tomcat01容器已经加入到 自定义网络my-network配置去了
2、测试
docker exec -it tomcat01 ping tomcat_my-network01
3、结论
- 跨网络操作,就需要使用 docker network connect [OPTIONS] NETWORK CONTAINER 连接
-- docker network connect 自定义网络 默认网络docker0下启动的Tomcat容器
docker network connect my-network tomcat01
5、实战:部署一个Redis集群
1、自定义网络
-- docker network create 自定义网络名称 --subnet 子网掩码
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、启动6个容器
-- 容器1
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
-- 容器2
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
-- 容器3
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
-- 容器4
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
-- 容器5
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
-- 容器6
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
- 脚本启动六个容器(使用这个脚本,我只启动成功了一个redis-6)
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server \
/etc/redis/redis.conf
4、进入一个redis,注意这里是 sh命令
docker exec -it redis-1 /bin/sh
5、创建集群
1、/data目录下有这两个文件,创建集群时才会成功
2、创建集群
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
-- 创建过程
uster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460 //主机一
Master[1] -> Slots 5461 - 10922 //主机二
Master[2] -> Slots 10923 - 16383 //主机三
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379 //从机一
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379 //从机二
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379 //从机三
M: 18d6a3ae8d3c664dc2b5f2af0d10ec45675a7d63 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: 3775df7377335d5360d56e6b378b2d8fb32e8cfd 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: 17e6d0212d5ba8d319503924f0c2dc0d738cbd88 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: ec9493167a6eb5a3d0810dd95c72f07eeb0f1d00 172.38.0.14:6379
replicates 17e6d0212d5ba8d319503924f0c2dc0d738cbd88
S: 3e026f328445d8ee9f07e6fa9d8427f66a3255a1 172.38.0.15:6379
replicates 18d6a3ae8d3c664dc2b5f2af0d10ec45675a7d63
S: a7c60e622cfd3ff619f4f91c2661897f9a9e0827 172.38.0.16:6379
replicates 3775df7377335d5360d56e6b378b2d8fb32e8cfd
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: 18d6a3ae8d3c664dc2b5f2af0d10ec45675a7d63 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 17e6d0212d5ba8d319503924f0c2dc0d738cbd88 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: a7c60e622cfd3ff619f4f91c2661897f9a9e0827 172.38.0.16:6379
slots: (0 slots) slave
replicates 3775df7377335d5360d56e6b378b2d8fb32e8cfd
M: 3775df7377335d5360d56e6b378b2d8fb32e8cfd 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: ec9493167a6eb5a3d0810dd95c72f07eeb0f1d00 172.38.0.14:6379
slots: (0 slots) slave
replicates 17e6d0212d5ba8d319503924f0c2dc0d738cbd88
S: 3e026f328445d8ee9f07e6fa9d8427f66a3255a1 172.38.0.15:6379
slots: (0 slots) slave
replicates 18d6a3ae8d3c664dc2b5f2af0d10ec45675a7d63
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
6、连接集群
redis-cli -c
7、查看集群信息
cluster info
8、查看节点信息
cluster nodes
9、测试Redis主机宕机,从机是否会自动补上主机的位置
1、从 节点信息中可以得出下图
能看出主从机,但它们之间的对应关系,暂时不知道;
查了下好像有工具可以显示各节点对应关系
2、写值
-- 将 name = "lisi" 写入Redis
set name lisi
- 结果显示:值被写入了redis-2主机
3、停止 redis-2容器
1、进入redis-1容器内,获取写入 redis-2主机的 name值
docker exec -it redis-1 /bin/sh
2、进入集群
redis-cli -c
3、获取 name的值
get name
- 结果显示在 redis-6号从机中获取到了
4、再次查看节点信息
cluster nodes
- redis-6从机变成了 主机
- 发现高可用完全没问题
10、找出主从机对应关系
1、写值
- 结果显示:值被写入了redis-1主机
2、停止 redis-1容器
3、进入 redis-3容器内
docker exec -it redis-3 /bin/sh
4、进入集群
redis-cli -c
5、获取 age的值
get age
- 结果显示在 redis-5号从机中获取到了
6、查看节点信息
cluster nodes