docker4-docker网络,容器编排,集群部署
1,docker网络
1.1,docker0
有三个网络环境,那么docker是如何处理容器网络访问的?
1.2,测试
docker run -d -p 80:8080 --name tomcat01 tomcat
docker exec -it tomcat01 ip addr
本地可以ping通容器内部
1.3,原理
-
只要安装了docker,就会有一个docker的ip-docker0(这里是172.17.0.1),这里的ip分配用的是桥接模式、veth-pair技术
- veth-pair:一对虚拟设备接口,成对出现,一端连着协议,一端彼此相连;veth-pair充当一个桥梁,连接各种虚拟网络设备。
- openstac,docker容器之间的连接,OVS的连接,都是使用veth-pair技术。
-
每启动一个docker容器,docker都会给容器分配一个ip(为tomcat分配172.17.0.2)
-
借助于宿主机,容器之间也可相互通信
容器和宿主机通信
容器之间通信
1.4,结论
-
容器和宿主机是可以通信的
-
容器和容器之间也是可以通信的,但使用docker0必须写明ip
-
所用容器默认启动不指定网络的情况下,都是docker0进行路由的,docker会给容器分配一个默认的可用ip
-
docker使用的是linux的桥接,docker0是所有容器的网桥
-
docker中的所有网络接口都是虚拟的,虚拟的转发效率高
-
容器删除,对应的网桥对就没了
2,link连接
2.1,测试及原理
是否可以使用容器名实现容器之间的通信?
docker exec -it tomcat01 ping tomcat02
发现不行
ping: tomcat02: Name or service not known
使用--link实现容器之间的连接
docker run -d -P --name tomcat03 --link tomcat02 tomcat
再使用容器名进行通信
[root@VM-0-11-centos ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.114 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.029 ms
[root@VM-0-11-centos ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
显示网络配置,发现03中将02直接写入了网络配置
[root@VM-0-11-centos ~]# docker exec -it tomcat03 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.3 tomcat02 3ba10f8d5d4e
172.17.0.4 40fb066c620a
[root@VM-0-11-centos ~]# docker exec -it tomcat02 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.3 3ba10f8d5d4e
--link就相当于在容器的网络配置中增加了目标容器的映射
2.2,步骤总结
-
使用--link连接
docker run -d -P --name tomcat03 --link tomcat02 tomcat
-
容器之间通信
[root@VM-0-11-centos ~]# docker exec -it tomcat03 ping tomcat02
3,自定义网络
3.1,网络模式
- bridge:桥接(docker默认,自己创建网络也使用该模式)
- none:不配置网络
- host:和宿主机共享网络
- container:容器网络连通(局限性大)
3.2,自定义网络测试
首先要明白,以下两种启动方式是相同的(启动时--net不写网络默认使用bridge模式):
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
docker0的特点:默认、通过容器名不能相互访问,--link可以打通连接,但是--link使用比较麻烦,因此我们可以自定义网络。
[root@VM-0-11-centos ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
8a3cfa860aaed386afc07a3b02f77edaec61a24a6095c7b6c165f1fa54bd7594
[root@VM-0-11-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
bc749755ff23 bridge bridge local
cc6fb605cde8 host host local
8a3cfa860aae mynet bridge local
00b2ae19fb37 none null local
[root@VM-0-11-centos ~]# docker network inspect mynet
使用自己创建的网络启动容器,通过容器名直接可以进行通信
[root@VM-0-11-centos ~]# docker run -d -p 80:8080 --name tomcat01 --net mynet tomcat
[root@VM-0-11-centos ~]# docker run -d -P --name tomcat02 --net mynet tomcat
[root@VM-0-11-centos ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.034 ms
[root@VM-0-11-centos ~]# docker exec -it tomcat02 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.082 ms
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.049 ms
3.3,自定义网络连通测试
使用默认模式再打开一个容器
[root@VM-0-11-centos ~]# docker run -d -P --name tomcat03 tomcat
023cff8d34af26a5db70af374b89b5c6baf1171c28f8ded417c8941f9ae597ed
尝试通信,发现不同网段的容器无法通信
[root@VM-0-11-centos ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
[root@VM-0-11-centos ~]# docker exec -it tomcat02 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.034 ms
将tomcat03和mynet连通,就可以实现01,02,03之间的通信了
[root@VM-0-11-centos ~]# docker network connect --help
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
[root@VM-0-11-centos ~]# docker network connect mynet tomcat03
[root@VM-0-11-centos ~]# docker exec -it tomcat03 ping tomcat03
PING tomcat03 (192.168.0.4) 56(84) bytes of data.
64 bytes from 023cff8d34af (192.168.0.4): icmp_seq=1 ttl=64 time=0.014 ms
查看mynet网络的具体信息,发现tomcat03已经加入到了mynet中(tomcat03也在docker01中/一个容器两个ip,docker01在docker network ls中显示为 bc749755ff23 bridge bridge local)
[root@VM-0-11-centos ~]# docker network inspect mynet
"Containers": {
"023cff8d34af26a5db70af374b89b5c6baf1171c28f8ded417c8941f9ae597ed": {
"Name": "tomcat03",
"EndpointID": "c57d075ff87400bf48d62e0c79dacf3fbf01417c678a62283ba62a370c815922",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
"585ecd5171e7722401708234aa7a110773d4f852e2992d6dcc22084c282f12ff": {
"Name": "tomcat01",
"EndpointID": "8a13b027417aa67db6b8a7bb58d12c003c3cb5138bc9fcd9718542fc53626bd0",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"8456029b09de3306abfe6b61a1d7ca001a01c9d5da58f2d7f836db66d5c206bc": {
"Name": "tomcat02",
"EndpointID": "85765f60d452116017ef69038e98b2e9f85d286b1a70b7e558c48e96e9a407cc",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
联通后的模型
3.4,步骤总结
-
自定义网络(根据不同类别的容器可以创建不同的网络,不同网络是相互隔离的;自定义网络相比与docker0的最大优势是连接自定义网络的容器可以使用容器名相互通信)
[root@VM-0-11-centos ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
-
使用自定义网络启动容器,就可以实现容器之间的相互通信(同一网络下)
[root@VM-0-11-centos ~]# docker run -d -p 80:8080 --name tomcat01 --net mynet tomcat [root@VM-0-11-centos ~]# docker run -d -P --name tomcat02 --net mynet tomcat [root@VM-0-11-centos ~]# docker exec -it tomcat01 ping tomcat02
-
网络连通,实现不同网络之间容器的相互通信
[root@VM-0-11-centos ~]# docker network connect --help Usage: docker network connect [OPTIONS] NETWORK CONTAINER [root@VM-0-11-centos ~]# docker network connect mynet tomcat03
4,单机多容器部署
创建网络
[root@VM-0-11-centos ~]# docker network create --subnet 172.38.0.0/16 redisNet
bde449dc56dcf00fa6ec761854c0fe59e64e768e7858be64aec67bcaa01791fb
通过脚本创建六个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
启动模板
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 redisNet --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
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 redisNet --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 redisNet --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 redisNet --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 redisNet --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 redisNet --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 redisNet --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
创建集群
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
[root@VM-0-11-centos conf]# docker exec -it redis-1 /bin/sh
/data # ls
appendonly.aof nodes.conf
/data # 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
>>> 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: 04bcb353c948d26d5b70b0f1f117351dbee65b18 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: 081e2c0f82416e7244e866f7017da67d85749568 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: a578b5ee518cb8bc8b6d70585238c4d89c586162 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: 79aa99f54ec9ad29540aed876894d68a47d22653 172.38.0.14:6379
replicates a578b5ee518cb8bc8b6d70585238c4d89c586162
S: 05905669b52e441c91ec93f05fcbd8f33b2c64bf 172.38.0.15:6379
replicates 04bcb353c948d26d5b70b0f1f117351dbee65b18
S: 421edea4f823d802f6e5689eed43d22d6eb5a085 172.38.0.16:6379
replicates 081e2c0f82416e7244e866f7017da67d85749568
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: 04bcb353c948d26d5b70b0f1f117351dbee65b18 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 79aa99f54ec9ad29540aed876894d68a47d22653 172.38.0.14:6379
slots: (0 slots) slave
replicates a578b5ee518cb8bc8b6d70585238c4d89c586162
S: 05905669b52e441c91ec93f05fcbd8f33b2c64bf 172.38.0.15:6379
slots: (0 slots) slave
replicates 04bcb353c948d26d5b70b0f1f117351dbee65b18
M: 081e2c0f82416e7244e866f7017da67d85749568 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: a578b5ee518cb8bc8b6d70585238c4d89c586162 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 421edea4f823d802f6e5689eed43d22d6eb5a085 172.38.0.16:6379
slots: (0 slots) slave
replicates 081e2c0f82416e7244e866f7017da67d85749568
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
6,docker compose
6.1,一些概念
-
定义并运行多个容器的docker应用,通过使用YAML文件配置应用服务,使用单个命令就可以从配置中创建并启动所有服务——批量容器编排。
-
使用compose基础可以分为三个步骤:
- Define your app’s environment with a
Dockerfile
so it can be reproduced anywhere.- 使用Dockerfile定义app环境,保证项目在任何地方都可以运行
- Define the services that make up your app in
docker-compose.yml
so they can be run together in an isolated environment.- services 是什么?(service-微服务,一个个单独的容器/应用,web,redis,mysql都可以是一个service,而多个service相互组合协同作用就成为一个完整的project并发挥作用,这样的一个project就是services)
- docker-compose.yml怎么写?
- Run
docker compose up
and the Docker compose command starts and runs your entire app. You can alternatively rundocker-compose up
using the docker-compose binary.- 启动项目
- Define your app’s environment with a
-
compose是docker官方的开源项目,需要安装。
-
Dockerfile让程序再任何地方都可以运行,但是容器一但多起来,一个个build和run会很麻烦;而使用compose,通过YAML文件一次就可以启动多个容器,很方便。
6.2,compose安装
https://docs.docker.com/compose/install/
镜像地址
curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
6.3,compose初体验
https://docs.docker.com/compose/gettingstarted/
-
写一个应用 app.py
-
dockerfile 将应用打包为镜像(单机)
-
docker compose yaml文件(定义整个服务,需要的环境:web、redis)(完整的上线服务)
-
启动compose项目(docker compose up)
流程:
-
创建网络
[root@VM-0-11-centos ~]# docker network ls NETWORK ID NAME DRIVER SCOPE c7e68254a7dc bridge bridge local d55a534055e0 composetest_default bridge local 项目中的内容都在同一个网络下d55a534055e0 composetest_default bridge local,可以通过容器名(域名)进行容器之间的信息传递
-
执行Docker-compose yami
-
启动服务
Creating composetest_web_1 ... done Creating composetest_redis_1 ... done 默认的服务名:文件名_服务名_num num是副本数目
-
-
总结:以前都是单个docker run启动容器,而docker-compose通过yaml文件可以一键启动/停止所有服务。
- docker镜像 run-》容器
- dockerfile 构建镜像(服务打包)
- docker-compose 启动服务(编排多个微服务/环境)
- docker网络
6.4,yaml规则
https://docs.docker.com/compose/compose-file/compose-file-v3/
yaml只有三层
第一层
version: ’‘ #版本,和docker engine对应
第二层
services: #服务(可以用哪些服务,在官网可以查看)
服务1: web
#服务配置(docker的服务配置)
images
build
network
volumes
...
服务2
...
服务3
...
第三层:其他配置 网络/卷,全局规则
volumes
networks
configs
6.5,搭建wordpress博客
https://docs.docker.com/samples/wordpress/
如果开源项目有yaml文件,则可以通过三步直接启动项目:
- 下载项目(docker-compose.yaml)
- Dockerfile文件(项目的依赖)
- 文件准备齐全,docker-compose up -d 一键启动
7,docker swarm
单机可以用docker compose,但是服务器一多起来就需要用集群的方式部署,docker swarm解决的就是这个问题。