前言:
如果我们的项目是分布式的微服务而且我们还用了docker容器,那么我们每启动一个实例都需要自己去docker bulid run
这样的操作,如果一个服务器要在100台服务器上部署,麻烦就来了。
docker-compose 就帮我解决了这一个问题。
通过编写 Dockerfile文件跟compose文件就可以实现一键部署
参考官方文档:
https://docs.docker.com/compose/install/
注意:使用docker-compose 需要基础的docker 服务 所以一定要先安装docker服务
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
[root@localhost ~]# sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 638 100 638 0 0 331 0 0:00:01 0:00:01 --:--:-- 331
100 11.6M 100 11.6M 0 0 264k 0 0:00:45 0:00:45 --:--:-- 534k
#查看安装的版本
[root@localhost home]# docker-compose -version
docker-compose version 1.26.2, build eefe0d31
这个服务就是官方提供的。
改服务器中使用到了python 跟redis 但是我们不用下载安装到本地机器。docker容器中会安装。
#创建一个目录
[root@localhost home]# mkdir composetest
#创建一个app.py 里边内容如下:
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
#再创建一个文件
[root@localhost ~]# mkdir requirements.txt
#里边内容是
flask
redis
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
docker-compose.yml
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
#这里发现报了一个错,是因为我们没有启动我们的docker服务,启动我们docker服务就可以了
[root@localhost composetest]# docker-compose up
ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running?
If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
#启动我们的docker 服务
[root@localhost composetest]# service docker start
[root@localhost composetest]# docker-compose up
Building web
Step 1/10 : FROM python:3.7-alpine
---> ae3ec9b0407e
Step 2/10 : WORKDIR /code
---> Using cache
---> 70ecbbb37bf5
Step 3/10 : ENV FLASK_APP app.py
---> Using cache
---> 9ef08ea0e2b7
Step 4/10 : ENV FLASK_RUN_HOST 0.0.0.0
---> Using cache
---> 967e0c411602
Step 5/10 : RUN apk add --no-cache gcc musl-dev linux-headers
---> Running in d4b270d752ee
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
(1/13) Installing libgcc (9.3.0-r2)
(2/13) Installing libstdc++ (9.3.0-r2)
(3/13) Installing binutils (2.34-r1)
(4/13) Installing gmp (6.2.0-r0)
(5/13) Installing isl (0.18-r0)
(6/13) Installing libgomp (9.3.0-r2)
...
redis_1 | 1:M 05 Aug 2020 10:53:48.408 * Ready to accept connections
web_1 | * Serving Flask app "app.py"
web_1 | * Environment: production
web_1 | WARNING: This is a development server. Do not use it in a production deployment.
web_1 | Use a production WSGI server instead.
web_1 | * Debug mode: off
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
启动该浏览器查看
查看我们的镜像
#这里发现了componse给我生跟下载的镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
composetest_web latest acb922109420 6 minutes ago 196MB
python 3.7-alpine ae3ec9b0407e 30 hours ago 41.7MB
redis alpine c7b388ce3d39 2 weeks ago 32.1MB
#查看正在运行的容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dc9992b04caf composetest_web "flask run" 8 minutes ago Up 3 minutes 0.0.0.0:5000->5000/tcp composetest_web_1
70358a6b7dcf redis:alpine "docker-entrypoint.s…" 8 minutes ago Up 3 minutes 6379/tcp composetest_redis_1
如果想停止compose 使用
$ docker-compose down
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
#增加当前目录(也可以指定目录)挂载目录 到我们的 web容器中
volumes:
- .:/code
environment:
FLASK_ENV: development
redis:
image: "redis:alpine"
#重新编译执行
[root@localhost composetest]# docker-compose up
Starting composetest_redis_1 ... done
Recreating composetest_web_1 ... done
....
web_1 | * Serving Flask app "app.py"
web_1 | * Environment: production
web_1 | WARNING: This is a development server. Do not use it in a production deployment.
web_1 | Use a production WSGI server instead.
web_1 | * Debug mode: off
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
#进入容器内部查看 有我们的挂载目录
[root@localhost ~]# docker exec -it b7ded709ef70 /bin/bash
OCI runtime exec failed: exec failed: container_linux.go:349: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown
[root@localhost ~]# docker exec -it b7ded709ef70 /bin/sh
/code # ll
/bin/sh: ll: not found
/code # ls
Dockerfile __pycache__ app.py docker-compose.yml requirements.txt
/code #
#修改我们app.py return的内容,让我们看出变化就行
#因为我们将目录之间挂载到了容器内部所以 我不用重新编译
按理说修改py文件不需要重新编译就可以生效,但是我这里不行,重新部署以后才生效(docker-compose up)
后台启动运行
单独运行某一个 容器
如果你启动的时候用的后台启动,那么停止的时候需要用到这个命令
也可以停止的时候将挂载的卷也停止
docker-compose down --volumes
使用这个命令的时候要在运行 compose的目录下边才可以
如果我们想删除不再使用的容器,可以用这个命令
使用compose 他会自动给我创建一个他的网络
[root@localhost composetest]# docker network ls
NETWORK ID NAME DRIVER SCOPE
97b350eb250b bridge bridge local
93420c0b315f composetest_default bridge local
6548c36a41d1 host host local
49146853ccd2 none null local
bf4e79dbc031 redis bridge local
app.py里边连接redis 没有配置ip 就是应为这个原因。默认通过容器名称就可以ping通
官方文档地址:
https://docs.docker.com/compose/compose-file/
规则介绍:
1、Dockerfile里边可以使用的命令这里都可以使用
2、docker-compose.yml里边必须包含 两个 version 跟services
version:这个根据官方来写,这个版本号跟docker容器相关
services:就是我们需要编排的每一个容器,这个容器可以是我们自己构建的也可以是从远程库下载的。
总结:
docker-compose.yml 编写就需要三层
1、version #指定版本号
2、services #需要的容器
3、其他 比如挂载 网络等等
version: "3.8" #版本号
services: #server标签
#服务器一
redis:
image: redis:alpine
ports:
- "6379"
networks:
- frontend
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
#服务器二
db:
image: postgres:9.4
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
max_replicas_per_node: 1
constraints:
- "node.role==manager"
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- "5000:80"
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
ports:
- "5001:80"
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints:
- "node.role==manager"
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints:
- "node.role==manager"
#网络相关配置
networks:
frontend:
backend:
#卷相关 就是挂的目录
volumes:
db-data:
如果某一个服务器启动依赖其他的服务,可以使用这个标签
version: "3.8"
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
官网地址:https://docs.docker.com/compose/
拿到项目的docker-compose.yml执行运行
[root@localhost my_wordpress]# ll
总用量 4
-rw-r--r--. 1 root root 591 8月 5 20:08 docker-compose.yml
[root@localhost my_wordpress]# docker-compose up -d
如果想单纯使用docker 启动一个redis-cluster集群
点击这里跳转:
这里我们使用一个批量的脚本生成6个redis实例的配置文件
#创建一个存放我们docker-compose.yml的目录
#我们生成的配置文件也放到这个里边统一管理
[root@localhost home]# mkdir -p /home/redis-compose/
#进入这个目录编写脚本文件
[root@localhost redis-compose]# ll
-rwxr-xr-x. 1 root root 458 8月 6 01:47 redis-cluter.sh
redis-cluter.sh 内容:
for port in $(seq 1 6)
do
mkdir -p /home/redis-compose/node-${port}/conf
mkdir -p /home/redis-compose/node-${port}/data
touch /home/redis-compose/node-${port}/conf/redis.conf
cat << EOF >> /home/redis-compose/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
#这里的ip地址要注意 跟我docker-compose.yml里边networks要对应
cluster-announce-ip 172.1.1.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
#文件生成以后的目录结构
#注意node-x 目录里边是有内容的,具体看上边的那个脚本文件
[root@localhost redis-compose]# ll
总用量 8
-rw-r--r--. 1 root root 2624 8月 6 01:39 docker-compose.yml
drwxr-xr-x. 4 root root 30 8月 6 01:47 node-1
drwxr-xr-x. 4 root root 30 8月 6 01:47 node-2
drwxr-xr-x. 4 root root 30 8月 6 01:47 node-3
drwxr-xr-x. 4 root root 30 8月 6 01:47 node-4
drwxr-xr-x. 4 root root 30 8月 6 01:47 node-5
drwxr-xr-x. 4 root root 30 8月 6 01:47 node-6
-rwxr-xr-x. 1 root root 458 8月 6 01:47 redis-cluter.sh
[root@localhost redis-compose]#
version: '3'
services:
redis-c-1:
image: redis:5.0.9-alpine3.11
container_name: redis-c-1
networks:
app_net:
ipv4_address: 172.1.1.11
ports:
- 6371:6379
- 16371:16379
volumes:
- ./node-1/conf/redis.conf:/etc/redis/redis.conf:rw
- ./node-1/data:/data:rw
command:
redis-server /etc/redis/redis.conf
redis-c-2:
image: redis:5.0.9-alpine3.11
container_name: redis-c-2
networks:
app_net:
ipv4_address: 172.1.1.12
ports:
- 6372:6379
- 16372:16379
volumes:
- ./node-2/conf/redis.conf:/etc/redis/redis.conf:rw
- ./node-2/data:/data:rw
command:
redis-server /etc/redis/redis.conf
redis-c-3:
image: redis:5.0.9-alpine3.11
container_name: redis-c-3
networks:
app_net:
ipv4_address: 172.1.1.13
ports:
- 6373:6379
- 16373:16379
volumes:
- ./node-3/conf/redis.conf:/etc/redis/redis.conf:rw
- ./node-3/data:/data:rw
command:
redis-server /etc/redis/redis.conf
redis-c-4:
image: redis:5.0.9-alpine3.11
container_name: redis-c-4
networks:
app_net:
ipv4_address: 172.1.1.14
ports:
- 6374:6379
- 16374:16379
volumes:
- ./node-4/conf/redis.conf:/etc/redis/redis.conf:rw
- ./node-4/data:/data:rw
command:
redis-server /etc/redis/redis.conf
redis-c-5:
image: redis:5.0.9-alpine3.11
container_name: redis-c-5
networks:
app_net:
ipv4_address: 172.1.1.15
ports:
- 6375:6379
- 16375:16379
volumes:
- ./node-5/conf/redis.conf:/etc/redis/redis.conf:rw
- ./node-5/data:/data:rw
command:
redis-server /etc/redis/redis.conf
redis-c-6:
image: redis:5.0.9-alpine3.11
container_name: redis-c-6
networks:
app_net:
ipv4_address: 172.1.1.16
ports:
- 6376:6379
- 16376:16379
volumes:
- ./node-6/conf/redis.conf:/etc/redis/redis.conf:rw
- ./node-6/data:/data:rw
command:
redis-server /etc/redis/redis.conf
networks:
app_net:
ipam:
driver: default
config:
- subnet: "172.1.1.0/16"
#使用 docker-compose 启动我们编排的容器
#注意如果你的compose文件名称不是docker-compose.yml 需要 用 -f 参数去指定你的文件名称
# 如果想后台运行 请加 -d 参数
[root@localhost redis-compose]# docker-compose up
Creating redis-c-5 ... done
Creating redis-c-1 ... done
Creating redis-c-4 ... done
Creating redis-c-2 ... done
Creating redis-c-3 ... done
Creating redis-c-6 ... done
Attaching to redis-c-3, redis-c-4, redis-c-2, redis-c-5, redis-c-1, redis-c-6
redis-c-1 | 1:C 05 Aug 2020 17:49:41.901 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-c-1 | 1:C 05 Aug 2020 17:49:41.901 # Redis version=5.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
redis-c-1 | 1:C 05 Aug 2020 17:49:41.901 # Configuration loaded
redis-c-1 | 1:M 05 Aug 2020 17:49:41.902 * No cluster configuration found, I'm af5824e59700e395bf61bf4f2327de2b8ad001d6
redis-c-1 | 1:M 05 Aug 2020 17:49:41.903 * Running mode=cluster, port=6379.
redis-c-1 | 1:M 05 Aug 2020 17:49:41.903 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
...
redis-c-6 | 1:S 05 Aug 2020 17:51:14.067 * Background AOF rewrite terminated with success
redis-c-6 | 1:S 05 Aug 2020 17:51:14.067 * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
redis-c-6 | 1:S 05 Aug 2020 17:51:14.067 * Background AOF rewrite finished successfully
#这里可以看到启动成功了
#查看 我们redis 集群docker
[root@localhost redis-compose]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af8c19edbf95 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 17 minutes ago Up 17 minutes 0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp redis-c-1
c2ba79b90384 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 17 minutes ago Up 17 minutes 0.0.0.0:6376->6379/tcp, 0.0.0.0:16376->16379/tcp redis-c-6
bcdf96e04d30 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 17 minutes ago Up 17 minutes 0.0.0.0:6375->6379/tcp, 0.0.0.0:16375->16379/tcp redis-c-5
9a70a5daa05b redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 17 minutes ago Up 17 minutes 0.0.0.0:6374->6379/tcp, 0.0.0.0:16374->16379/tcp redis-c-4
dde18aac17c4 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 17 minutes ago Up 17 minutes 0.0.0.0:6373->6379/tcp, 0.0.0.0:16373->16379/tcp redis-c-3
0e2da8dd3778 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 17 minutes ago Up 17 minutes 0.0.0.0:6372->6379/tcp, 0.0.0.0:16372->16379/tcp redis-c-2
#进入docker
[root@localhost redis-compose]# docker exec -it redis-c-1 /bin/sh
# 配置集群
/data # redis-cli --cluster create 172.1.1.11:6379 172.1.1.12:6379 172.1.1.13:6379 172.1.1.14:6379 172.1.1.15:6379 172.1.1.16:637
9 --cluster-replicas 1
#设置成功后查看集群信息
#注意定义要 加-c 参数 连接cluster集群需要
/data # redis-cli -c
127.0.0.1:6379> CLUSTER nodes
fea4e8577d149b6a5cd7f29751a69d533f45f796 172.1.1.13:6379@16379 master - 0 1596649888558 3 connected 10923-16383
7f823ce1a787f4bd1a4c9cd76fc1d7b581e1d9c9 172.1.1.12:6379@16379 master - 0 1596649888048 2 connected 5461-10922
af5824e59700e395bf61bf4f2327de2b8ad001d6 172.1.1.11:6379@16379 myself,master - 0 1596649888000 1 connected 0-5460
bba53ac2cd0046cb8017ea29b0a07060bfe13863 172.1.1.16:6379@16379 slave 7f823ce1a787f4bd1a4c9cd76fc1d7b581e1d9c9 0 1596649889067 6 connected
cff7ec4bec6409760983ba3cff4403a4e596493e 172.1.1.14:6379@16379 slave fea4e8577d149b6a5cd7f29751a69d533f45f796 0 1596649889000 4 connected
d79a17a36e67f3a6a27d291111ee81d7b1f1cfff 172.1.1.15:6379@16379 slave af5824e59700e395bf61bf4f2327de2b8ad001d6 0 1596649888000 5 connected
如果我们想停止我们的redis 集群 使用
docker-compose stop 就可以停止
docker-compose up 就可以启动
不用在每次一个一个启动