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
version: '3'
services:
wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD: root
networks:
- my-bridge
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
volumes:
- mysql-data:/var/lib/mysql
networks:
- my-bridge
volumes:
mysql-data:
networks:
my-bridge:
driver: bridge
docker compose
linux下需要单独安装docker compose,windows和mac不需要。
curl -L https://github.com/docker/compose/releases/download/1.7.0/docker-compose-`uname -s `-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
常用命令
[root@localhost docker-compose]# pwd
/docker/docker-compose
[root@localhost docker-compose]# ls /docker/docker-compose/
docker-compose.yml
[root@localhost docker-compose]# docker-compose -f docker-compose.yml up
# 也可以缺省为:启动当前目录下docker-compose文件中定义的容器
[root@localhost docker-compose]# docker-compose up
# 后台执行:平时用的比较多
[root@localhost docker-compose]# docker-compose up -d
# 查看当前目录下docker-compose文件中定义的容器运行状态
[root@localhost docker-compose]# docker-compose ps
# 停止容器组
[root@localhost docker-compose]# docker-compose stop
# 停止容器组,并删除容器、networks、volumes
[root@localhost docker-compose]# docker-compose down
# 列举出docker-compose.yml中所定义的container及它使用的image
[root@localhost docker-compose]# docker-compose images
# 进入容器后面跟着docker-compose.yml中定义的service
[root@localhost docker-compose]# docker-compose exec mysql bash
[root@localhost docker-compose]# docker-compose exec wordpress bash
docker-compose快速上手
编写一个最简单的docker-compose.yml
version: '3'
services:
redis:
image: mycentos:redis
compose相关操作
操作docker-compose一定要在配置文件docker-compose.yml文件路径下操作。
# 后台启动容器
[root@master docker-compose]# docker-compose up -d
Creating network "docker-compose_default" with the default driver
Creating docker-compose_redis_1 ... done
[root@master docker-compose]# docker ps | grep redis
ed82c76ba738 mycentos:redis "/bin/sh -c '/usr/lo…" 24 seconds ago Up 23 seconds docker-compose_redis_1
# 查看容器
[root@master docker-compose]# docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------
docker-compose_redis_1 /bin/sh -c /usr/local/redi ... Up
# 进入容器
[root@master docker-compose]# docker-compose exec redis bash
[root@ed82c76ba738 /]#
# 停止容器
[root@master docker-compose]# docker-compose stop
Stopping docker-compose_redis_1 ... done
[root@master docker-compose]# docker-compose ps
Name Command State Ports
------------------------------------------------------------------------
docker-compose_redis_1 /bin/sh -c /usr/local/redi ... Exit 0
# 启动容器
[root@master docker-compose]# docker-compose start
Starting redis ... done
[root@master docker-compose]# docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------
docker-compose_redis_1 /bin/sh -c /usr/local/redi ... Up
# 删除容器
[root@master docker-compose]# docker-compose down
Stopping docker-compose_redis_1 ... done
Removing docker-compose_redis_1 ... done
Removing network docker-compose_default
# 删除容器并且删除volumes
[root@master docker-compose]# docker-compose down --volumes
docker-compose参考案例
docker-compose.yml分为三大部分:version、services、networks。通过编写docker-compose.yml文件可以设置网络模式、端口映射、文件共享、同时管理多个容器。
docker-compose.yml
version: '3'
services:
nginx:
image: mycentos:nginx
network_mode: "host"
volumes:
- /docker/nginx/html:/usr/local/nginx/html
- /docker/nginx/logs:/usr/local/nginx/logs
command: /usr/local/nginx/sbin/nginx -g "daemon off;"
redis:
image: mycentos:redis
ports:
- "6380:6379"
启动
[root@master docker-compose]# docker-compose up -d
Creating network "docker-compose_default" with the default driver
Creating docker-compose_nginx_1 ... done
Creating docker-compose_redis_1 ... done
docker-compose搭建个人博客wordpress
docker-compose.yml
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql # 采用的是卷标的形式挂载(注意:- db_data是参数,可以变,自 定义,必须与下面对应)
restart: always # 自动重启,保证服务在线
environment:
MYSQL_ROOT_PASSWORD: somewordpress # 数据库远程连接的密码
MYSQL_DATABASE: wordpress # 数据库名称
MYSQL_USER: wordpress # 用户名称
MYSQL_PASSWORD: wordpress # 用户密码
wordpress:
depends_on: #只有容器db(mysql)成功启动之后,才可以运行wordpress容器,并且等同于 --link 的功能
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
如何查看容器自定义的volumes
# 查看所有卷
[root@master docker-compose]# docker volume ls
# 查看具体卷的信息
[root@master docker-compose]# docker volume inspect wordpress_db_data | grep "Mountpoint"
此宿主机路径挂载至容器内/var/lib/mysql
使用docker compose构建flask app
# Dockerfile
[root@localhost flask-redis]# cat Dockerfile
FROM python:2.7
LABEL maintaner="xxx"
COPY . /app
WORKDIR /app
RUN pip install flask redis
-i http://pypi.douban.com/simple --trusted-host pypi.douban.com
EXPOSE 5000
# docker-compose.yml
[root@localhost flask-redis]# cat docker-compose.yml
version: "3"
services:
redis:
image: redis
web:
build:
context: .
dockerfile: Dockerfile
ports:
- 8080:5000
environment:
REDIS_HOST: redis
# app.py
[root@localhost flask-redis]# cat app.py
from flask import Flask
from redis import Redis
import os
import socket
app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)
# 启动容器组
[root@localhost flask-redis]# docker-compose up
水平扩展和负载均衡之Scale
假设启动3个web(servbice)作为负载均衡
- scale只能在单机对容器进行扩容/缩容,如果单机的资源有上限,需要将同一个容器扩容并运行在不同的Docker节点上,需要使用swarm。
[root@localhost lb-scale]# pwd
/docker/docker-compose/lb-scale
# docker-compose.yml
[root@localhost lb-scale]# cat docker-compose.yml
version: "3"
services:
redis:
image: redis
web:
build:
context: .
dockerfile: Dockerfile
environment:
REDIS_HOST: redis
lb:
image: dockercloud/haproxy
links:
- web
ports:
- 8080:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# Dockerfile
[root@localhost lb-scale]# cat Dockerfile
FROM python:2.7
LABEL maintaner="xxx"
COPY . /app
WORKDIR /app
RUN pip install flask redis -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
EXPOSE 80
# app.py
[root@localhost lb-scale]# cat app.py
from flask import Flask
from redis import Redis
import os
import socket
app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
if __name__ == "__main__":
app.run(host="0.0.0.0", port=80, debug=True)
# 启动容器组
[root@localhost lb-scale]# docker-compose up
# 查看容器组中各容器状态
[root@localhost lb-scale]# docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------
lb-scale_lb_1 /sbin/tini -- dockercloud- ... Up 1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
lb-scale_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
lb-scale_web_1 python app.py Up 80/tcp
# 访问发现此时 hostname是 9b57020bdd3c.
是web的hostname
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 9 times and my hostname is 9b57020bdd3c.
# 验证hostname
[root@localhost lb-scale]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0cae2375e720 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
f64a9093ba45 redis "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 6379/tcp lb-scale_redis_1
9b57020bdd3c lb-scale_web "python app.py" 3 minutes ago Up 3 minutes 80/tcp lb-scale_web_1
# 使用scale做水平扩展:web 容器的数量。
[root@localhost lb-scale]# docker-compose up --scale web=5 -d
Starting lb-scale_web_1 ... done
lb-scale_redis_1 is up-to-date
Creating lb-scale_web_2 ... done
Creating lb-scale_web_3 ... done
Creating lb-scale_web_4 ... done
Creating lb-scale_web_5 ... done
lb-scale_lb_1 is up-to-date
# 验证
[root@localhost lb-scale]# docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------
lb-scale_lb_1 /sbin/tini -- dockercloud- ... Up 1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
lb-scale_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
lb-scale_web_1 python app.py Up 80/tcp
lb-scale_web_2 python app.py Up 80/tcp
lb-scale_web_3 python app.py Up 80/tcp
lb-scale_web_4 python app.py Up 80/tcp
lb-scale_web_5 python app.py Up 80/tcp
[root@localhost lb-scale]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2d3206abc32e lb-scale_web "python app.py" About a minute ago Up About a minute 80/tcp lb-scale_web_3
08114069ebb6 lb-scale_web "python app.py" About a minute ago Up About a minute 80/tcp lb-scale_web_2
2ad3c66ab1e3 lb-scale_web "python app.py" About a minute ago Up About a minute 80/tcp lb-scale_web_5
3edd57819130 lb-scale_web "python app.py" About a minute ago Up About a minute 80/tcp lb-scale_web_4
0cae2375e720 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
f64a9093ba45 redis "docker-entrypoint.s…" 9 minutes ago Up 9 minutes 6379/tcp lb-scale_redis_1
9b57020bdd3c lb-scale_web "python app.py" 9 minutes ago Up 9 minutes 80/tcp lb-scale_web_1
# 再次访问,发现第六次6次访问的hostname和第一次的一致,可判断Haproxy访问web的方式为轮询。
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 10 times and my hostname is 9b57020bdd3c.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 11 times and my hostname is 08114069ebb6.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 12 times and my hostname is 2d3206abc32e.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 13 times and my hostname is 3edd57819130.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 14 times and my hostname is 2ad3c66ab1e3.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 15 times and my hostname is 9b57020bdd3c.
# 服务缩容(修改容器名称后面的数量即可)
[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,实时从数据库中拉取数据展示给前端用户。