Docker Compose多容器部署
多容器的 APP 的痛点
- 要从 Dockerfile build image 或者 Dockerhub 拉取 iage
- 要创建多个 container
- 要管理这些 container(启动停止删除)
- 一个应用可能由多个容器之间相互配合完成,追个容器进行管理成本高,将多个容器定义为一个组,对组进行统一的管理。
- 微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知。
Docker Compose 简介
使用 Docker Compose 可以轻松、高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具。
- Docker Compose 是一个工具。
- 这个工具可以通过 yml 文件定义多容器的 docker APP。
- 通过一条命令就可以根据 yml 文件的定义去创建或管理多容器。
yml 概念
Services
- 一个 service 代表一个 container,这个 container 可以从 dockerhub 的 image 创建而来,或是从本地的 Dockerfile build 构建的 image 创建而来。
- Service 的启动类似 docker run,我们可以给其指定 network 和 volume,所以可以给 service 指定 network 和 Volume 的引用。
docker-compose.yml
1version: '3'
2
3services:
4
5 wordpress:
6 image: wordpress
7 ports:
8 - 8080:80
9 environment:
10 WORDPRESS_DB_HOST: mysql
11 WORDPRESS_DB_PASSWORD: root
12 networks:
13 - my-bridge
14
15 mysql:
16 image: mysql
17 environment:
18 MYSQL_ROOT_PASSWORD: root
19 MYSQL_DATABASE: wordpress
20 volumes:
21 - mysql-data:/var/lib/mysql
22 networks:
23 - my-bridge
24
25volumes:
26 mysql-data:
27
28networks:
29 my-bridge:
30 driver: bridge
docker compose
Linux 下需要单独安装 docker compose,windows 和 mac 不需要。
1curl -L https://github.com/docker/compose/releases/download/1.7.0/docker-compose-`uname -s `-`uname -m` > /usr/local/bin/docker-compose
2chmod +x /usr/local/bin/docker-compose
常用命令
1[root@localhost docker-compose]# pwd
2/docker/docker-compose
3[root@localhost docker-compose]# ls /docker/docker-compose/
4docker-compose.yml
5[root@localhost docker-compose]# docker-compose -f docker-compose.yml up
6# 也可以缺省为:启动当前目录下docker-compose文件中定义的容器
7[root@localhost docker-compose]# docker-compose up
8# 后台执行:平时用的比较多
9[root@localhost docker-compose]# docker-compose up -d
10
11# 查看当前目录下docker-compose文件中定义的容器运行状态
12[root@localhost docker-compose]# docker-compose ps
13
14# 停止容器组
15[root@localhost docker-compose]# docker-compose stop
16
17# 停止容器组,并删除容器、networks、volumes
18[root@localhost docker-compose]# docker-compose down
19
20# 列举出docker-compose.yml中所定义的container及它使用的image
21[root@localhost docker-compose]# docker-compose images
22
23# 进入容器后面跟着docker-compose.yml中定义的service
24[root@localhost docker-compose]# docker-compose exec mysql bash
25[root@localhost docker-compose]# docker-compose exec wordpress bash
docker-compose 快速上手
编写一个最简单的 docker-compose.yml
1version: '3'
2services:
3 redis:
4 image: mycentos:redis
compose 相关操作
操作 docker-compose 一定要在配置文件 docker-compose.yml 文件路径下操作。
1# 后台启动容器
2[root@master docker-compose]# docker-compose up -d
3Creating network "docker-compose_default" with the default driver
4Creating docker-compose_redis_1 ... done
5[root@master docker-compose]# docker ps | grep redis
6ed82c76ba738 mycentos:redis "/bin/sh -c '/usr/lo…" 24 seconds ago Up 23 seconds docker-compose_redis_1
7
8# 查看容器
9[root@master docker-compose]# docker-compose ps
10 Name Command State Ports
11-----------------------------------------------------------------------
12docker-compose_redis_1 /bin/sh -c /usr/local/redi ... Up
13
14# 进入容器
15[root@master docker-compose]# docker-compose exec redis bash
16[root@ed82c76ba738 /]#
17
18# 停止容器
19[root@master docker-compose]# docker-compose stop
20Stopping docker-compose_redis_1 ... done
21[root@master docker-compose]# docker-compose ps
22 Name Command State Ports
23------------------------------------------------------------------------
24docker-compose_redis_1 /bin/sh -c /usr/local/redi ... Exit 0
25
26# 启动容器
27[root@master docker-compose]# docker-compose start
28Starting redis ... done
29[root@master docker-compose]# docker-compose ps
30 Name Command State Ports
31-----------------------------------------------------------------------
32docker-compose_redis_1 /bin/sh -c /usr/local/redi ... Up
33
34# 删除容器
35[root@master docker-compose]# docker-compose down
36Stopping docker-compose_redis_1 ... done
37Removing docker-compose_redis_1 ... done
38Removing network docker-compose_default
39
40# 删除容器并且删除volumes
41[root@master docker-compose]# docker-compose down --volumes
docker-compose 参考案例
docker-compose.yml 分为三大部分:version、services、networks。通过编写 docker-compose.yml 文件可以设置网络模式、端口映射、文件共享、同时管理多个容器。
docker-compose.yml
1version: '3'
2services:
3 nginx:
4 image: mycentos:nginx
5 network_mode: "host"
6 volumes:
7 - /docker/nginx/html:/usr/local/nginx/html
8 - /docker/nginx/logs:/usr/local/nginx/logs
9 command: /usr/local/nginx/sbin/nginx -g "daemon off;"
10 redis:
11 image: mycentos:redis
12 ports:
13 - "6380:6379"
启动
1[root@master docker-compose]# docker-compose up -d
2Creating network "docker-compose_default" with the default driver
3Creating docker-compose_nginx_1 ... done
4Creating docker-compose_redis_1 ... done
docker-compose 搭建个人博客 wordpress
docker-compose.yml
1version: '3.3'
2services:
3 db:
4 image: mysql:5.7
5 volumes:
6 - db_data:/var/lib/mysql # 采用的是卷标的形式挂载(注意:- db_data是参数,可以变,自 定义,必须与下面对应)
7 restart: always # 自动重启,保证服务在线
8 environment:
9 MYSQL_ROOT_PASSWORD: somewordpress # 数据库远程连接的密码
10 MYSQL_DATABASE: wordpress # 数据库名称
11 MYSQL_USER: wordpress # 用户名称
12 MYSQL_PASSWORD: wordpress # 用户密码
13
14 wordpress:
15 depends_on: #只有容器db(mysql)成功启动之后,才可以运行wordpress容器,并且等同于 --link 的功能
16 - db
17 image: wordpress:latest
18 ports:
19 - "8000:80"
20 restart: always
21 environment:
22 WORDPRESS_DB_HOST: db:3306
23 WORDPRESS_DB_USER: wordpress
24 WORDPRESS_DB_PASSWORD: wordpress
25 WORDPRESS_DB_NAME: wordpress
26volumes:
27 db_data: {}
如何查看容器自定义的 volumes
1# 查看所有卷
2[root@master docker-compose]# docker volume ls
3
4# 查看具体卷的信息
5[root@master docker-compose]# docker volume inspect wordpress_db_data | grep "Mountpoint"
6此宿主机路径挂载至容器内/var/lib/mysql
使用 docker compose 构建 flask app
1# Dockerfile
2[root@localhost flask-redis]# cat Dockerfile
3FROM python:2.7
4LABEL maintaner="xxx"
5COPY . /app
6WORKDIR /app
7RUN pip install flask redis
8 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
9EXPOSE 5000
10
11# docker-compose.yml
12[root@localhost flask-redis]# cat docker-compose.yml
13version: "3"
14services:
15
16 redis:
17 image: redis
18
19 web:
20 build:
21 context: .
22 dockerfile: Dockerfile
23 ports:
24 - 8080:5000
25 environment:
26 REDIS_HOST: redis
27
28# app.py
29[root@localhost flask-redis]# cat app.py
30from flask import Flask
31from redis import Redis
32import os
33import socket
34
35app = Flask(__name__)
36redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
37
38@app.route('/')
39def hello():
40 redis.incr('hits')
41 return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
42
43if __name__ == "__main__":
44 app.run(host="0.0.0.0", port=5000, debug=True)
45
46# 启动容器组
47[root@localhost flask-redis]# docker-compose up
水平扩展和负载均衡之 Scale
假设启动 3 个 web(servbice)作为负载均衡
- scale 只能在单机对容器进行扩容/缩容,如果单机的资源有上限,需要将同一个容器扩容并运行在不同的 Docker 节点上,需要使用 swarm。
1[root@localhost lb-scale]# pwd
2/docker/docker-compose/lb-scale
3
4# docker-compose.yml
5[root@localhost lb-scale]# cat docker-compose.yml
6version: "3"
7
8services:
9
10 redis:
11 image: redis
12
13 web:
14 build:
15 context: .
16 dockerfile: Dockerfile
17 environment:
18 REDIS_HOST: redis
19
20 lb:
21 image: dockercloud/haproxy
22 links:
23 - web
24 ports:
25 - 8080:80
26 volumes:
27 - /var/run/docker.sock:/var/run/docker.sock
28
29# Dockerfile
30[root@localhost lb-scale]# cat Dockerfile
31FROM python:2.7
32LABEL maintaner="xxx"
33COPY . /app
34WORKDIR /app
35RUN pip install flask redis -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
36EXPOSE 80
37
38# app.py
39[root@localhost lb-scale]# cat app.py
40from flask import Flask
41from redis import Redis
42import os
43import socket
44
45app = Flask(__name__)
46redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
47
48@app.route('/')
49def hello():
50 redis.incr('hits')
51 return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
52
53if __name__ == "__main__":
54 app.run(host="0.0.0.0", port=80, debug=True)
55
56# 启动容器组
57[root@localhost lb-scale]# docker-compose up
58
59# 查看容器组中各容器状态
60[root@localhost lb-scale]# docker-compose ps
61 Name Command State Ports
62--------------------------------------------------------------------------------------
63lb-scale_lb_1 /sbin/tini -- dockercloud- ... Up 1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
64lb-scale_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
65lb-scale_web_1 python app.py Up 80/tcp
66
67# 访问发现此时 hostname是 9b57020bdd3c.
68 是web的hostname
69[root@localhost lb-scale]# curl 127.0.0.1:8080
70Hello Container World! I have been seen 9 times and my hostname is 9b57020bdd3c.
71
72# 验证hostname
73[root@localhost lb-scale]# docker ps
74CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
750cae2375e720 dockercloud/haproxy "/sbin/tini -- docke…" 3 minutes ago Up 3 minutes 443/tcp, 1936/tcp, 0.0.0.0:8080->80/tcp lb-scale_lb_1
76f64a9093ba45 redis "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 6379/tcp lb-scale_redis_1
779b57020bdd3c lb-scale_web "python app.py" 3 minutes ago Up 3 minutes 80/tcp lb-scale_web_1
78
79# 使用scale做水平扩展:web 容器的数量。
80[root@localhost lb-scale]# docker-compose up --scale web=5 -d
81Starting lb-scale_web_1 ... done
82lb-scale_redis_1 is up-to-date
83Creating lb-scale_web_2 ... done
84Creating lb-scale_web_3 ... done
85Creating lb-scale_web_4 ... done
86Creating lb-scale_web_5 ... done
87lb-scale_lb_1 is up-to-date
88
89# 验证
90[root@localhost lb-scale]# docker-compose ps
91 Name Command State Ports
92--------------------------------------------------------------------------------------
93lb-scale_lb_1 /sbin/tini -- dockercloud- ... Up 1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
94lb-scale_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
95lb-scale_web_1 python app.py Up 80/tcp
96lb-scale_web_2 python app.py Up 80/tcp
97lb-scale_web_3 python app.py Up 80/tcp
98lb-scale_web_4 python app.py Up 80/tcp
99lb-scale_web_5 python app.py Up 80/tcp
100
101[root@localhost lb-scale]# docker ps
102CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1032d3206abc32e lb-scale_web "python app.py" About a minute ago Up About a minute 80/tcp lb-scale_web_3
10408114069ebb6 lb-scale_web "python app.py" About a minute ago Up About a minute 80/tcp lb-scale_web_2
1052ad3c66ab1e3 lb-scale_web "python app.py" About a minute ago Up About a minute 80/tcp lb-scale_web_5
1063edd57819130 lb-scale_web "python app.py" About a minute ago Up About a minute 80/tcp lb-scale_web_4
1070cae2375e720 dockercloud/haproxy "/sbin/tini -- docke…" 9 minutes ago Up 9 minutes 443/tcp, 1936/tcp, 0.0.0.0:8080->80/tcp lb-scale_lb_1
108f64a9093ba45 redis "docker-entrypoint.s…" 9 minutes ago Up 9 minutes 6379/tcp lb-scale_redis_1
1099b57020bdd3c lb-scale_web "python app.py" 9 minutes ago Up 9 minutes 80/tcp lb-scale_web_1
110
111# 再次访问,发现第六次6次访问的hostname和第一次的一致,可判断Haproxy访问web的方式为轮询。
112[root@localhost lb-scale]# curl 127.0.0.1:8080
113Hello Container World! I have been seen 10 times and my hostname is 9b57020bdd3c.
114[root@localhost lb-scale]# curl 127.0.0.1:8080
115Hello Container World! I have been seen 11 times and my hostname is 08114069ebb6.
116[root@localhost lb-scale]# curl 127.0.0.1:8080
117Hello Container World! I have been seen 12 times and my hostname is 2d3206abc32e.
118[root@localhost lb-scale]# curl 127.0.0.1:8080
119Hello Container World! I have been seen 13 times and my hostname is 3edd57819130.
120[root@localhost lb-scale]# curl 127.0.0.1:8080
121Hello Container World! I have been seen 14 times and my hostname is 2ad3c66ab1e3.
122[root@localhost lb-scale]# curl 127.0.0.1:8080
123Hello Container World! I have been seen 15 times and my hostname is 9b57020bdd3c.
124
125# 服务缩容(修改容器名称后面的数量即可)
126[root@localhost lb-scale]# docker-compose up --scale web=3 -d
docker compose 部署投票系统
- Voting App 采用 python,接收前端用户投票输入操作,并写入 Redis。
- Java worker 采用 Java,读取 Redis 中数据写入数据库。
- Result App 采用 Node.js,实时从数据库中拉取数据展示给前端用户。