简介
Docker-Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。Docker-Compose项目由Python编写,调用Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。
Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker-Compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例,Docker-Compose并没有解决负载均衡的问题,因此需要借助其它工具实现服务发现及负载均衡。
Docker-Compose的工程配置文件默认为docker-compose.yml,可通过环境变量COMPOSE_FILE或-f参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。
使用一个Dockerfile模板文件,可以让用户很方便的定义一个单独的应用容器。在工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个Web项目,除了Web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。
Docker-compose常用命令
- 查看配置:docker-compose config
- 后台启动:docker-compose up -d
- 构建镜像:docker-compose build
- 下载镜像:docker-compose pull
- 运行的:docker-compose ps
- 进程:docker-compose top
- 启动: docker-compose start
- 停止:docker-compose stop
docker-compose 模版文件
Compose允许用户通过一个docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。
Compose模板文件是一个定义服务、网络和卷的YAML文件。Compose模板文件默认路径是当前目录下的docker-compose.yml,可以使用.yml或.yaml作为文件扩展名。
Docker-Compose标准模板文件应该包含version、services、networks 三大部分,最关键的是services和networks两个部分。
version: "2.1"
services:
img-name:
image: xxxx
Compose目前有三个版本分别为Version 1,Version 2,Version 3,Compose区分Version 1和Version 2(Compose 1.6.0+,Docker Engine 1.10.0+)。Version 2支持更多的指令。Version 1将来会被弃用。
挂载文件
docker-compose支持两种方式设置持久化的文件
servicename:
image: image-name
volumes:
- /path/to/file:/path/to/container/file
这种方式将文件直接挂载到容器中,使用起来比较直观,但是需要管理本地路径。
servicename:
image: image-name
volumes:
- volume-name:/path/to/container/file
volumes:
volume-name: /path/to/local/file
使用docker volume ls命令可以查看本地挂载的文件。
使用docker volume inspect volume-name命令可以查看具体的真实地址。
具体示例
chenshifengdeMacBook-Pro:docker-compose chenshifeng$ pwd
/Users/chenshifeng/docker/docker-compose
chenshifengdeMacBook-Pro:docker-compose chenshifeng$ ls -a
. .. .env Dockerfile app.py docker-compose.yml
docker-compose.yml 文件
version: '3'
services:
web:
build:
context: .
depends_on:
- redis
ports:
- "5000:5000"
redis:
image: ${REDIS_VERSION}
restart: always
Dockerfile
FROM python:3.7-alpine
LABEL maintainer="shifeng"
#将工作路径设定为/code
WORKDIR /code
#创建环境变量给 Flask 使用
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
#复制 app.py 到容器内 /code 目录
COPY app.py /code
#安装 gcc 工具、python 的依赖
RUN pip install flask && pip install redis
#映射端口
EXPOSE 5000
STOPSIGNAL SIGTERM
#为容器设置默认启动命令
CMD ["flask","run"]
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 Wirld! I have been see {} times.
'.format(count)
.env 文件
REDIS_VERSION=redis:alpine
chenshifengdeMacBook-Pro:docker-compose chenshifeng$ docker-compose up
Creating network "docker-compose_default" with the default driver
Pulling redis (redis:alpine)...
alpine: Pulling from library/redis
801bfaa63ef2: Pull complete
9a8d0188e481: Pull complete
8a3f5c4e0176: Pull complete
51a20dbe2f6a: Pull complete
0aacff13b8d7: Pull complete
adc9264cf133: Pull complete
Digest: sha256:68d4030e07912c418332ba6fdab4ac69f0293d9b1daaed4f1f77bdeb0a5eb048
Status: Downloaded newer image for redis:alpine
Building web
Step 1/10 : FROM python:3.7-alpine
3.7-alpine: Pulling from library/python
801bfaa63ef2: Already exists
7678dd7631a2: Pull complete
673b2cf6feb8: Pull complete
924474d3e184: Pull complete
3531f307fdb1: Pull complete
Digest: sha256:a73d0fdab3235920c0df44d55c420e2c3096f1b1a95e5f913a0287eee4192bdb
Status: Downloaded newer image for python:3.7-alpine
---> 72e4ef8abf8e
Step 2/10 : LABEL maintainer="shifeng"
---> Running in 793121c1f8dd
Removing intermediate container 793121c1f8dd
---> ed4aff0b54e8
Step 3/10 : WORKDIR /code
---> Running in 98ee8098e153
Removing intermediate container 98ee8098e153
---> 4900195b572f
Step 4/10 : ENV FLASK_APP app.py
---> Running in 3e2758418f80
Removing intermediate container 3e2758418f80
---> 171470c2ac1b
Step 5/10 : ENV FLASK_RUN_HOST 0.0.0.0
---> Running in 04b8ad3e08a7
Removing intermediate container 04b8ad3e08a7
---> 1347210f446e
Step 6/10 : COPY app.py /code
---> 7e5a2528c571
Step 7/10 : RUN pip install flask && pip install redis
---> Running in 0e844207fd06
Collecting flask
Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB)
Collecting click>=5.1
Downloading click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting itsdangerous>=0.24
Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting Jinja2>=2.10.1
Downloading Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting MarkupSafe>=0.23
Downloading MarkupSafe-1.1.1.tar.gz (19 kB)
Collecting Werkzeug>=0.15
Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Building wheels for collected packages: MarkupSafe
Building wheel for MarkupSafe (setup.py): started
Building wheel for MarkupSafe (setup.py): finished with status 'done'
Created wheel for MarkupSafe: filename=MarkupSafe-1.1.1-py3-none-any.whl size=12629 sha256=5645144c3e873524880c2e8ece40cc7d195ef92acf2d7e2f4fbbdca8959411ac
Stored in directory: /root/.cache/pip/wheels/b9/d9/ae/63bf9056b0a22b13ade9f6b9e08187c1bb71c47ef21a8c9924
Successfully built MarkupSafe
Installing collected packages: MarkupSafe, Werkzeug, Jinja2, itsdangerous, click, flask
Successfully installed Jinja2-2.11.2 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 flask-1.1.2 itsdangerous-1.1.0
Collecting redis
Downloading redis-3.5.3-py2.py3-none-any.whl (72 kB)
Installing collected packages: redis
Successfully installed redis-3.5.3
Removing intermediate container 0e844207fd06
---> 53a70dd92c04
Step 8/10 : EXPOSE 5000
---> Running in 6987bd583661
Removing intermediate container 6987bd583661
---> e20fb875f578
Step 9/10 : STOPSIGNAL SIGTERM
---> Running in 31e0f0933348
Removing intermediate container 31e0f0933348
---> 48291e02cb4e
Step 10/10 : CMD ["flask","run"]
---> Running in 9405853c0548
Removing intermediate container 9405853c0548
---> bce891d25361
Successfully built bce891d25361
Successfully tagged docker-compose_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating docker-compose_redis_1 ... done
Creating docker-compose_web_1 ... done
Attaching to docker-compose_redis_1, docker-compose_web_1
redis_1 | 1:C 05 Jan 2021 15:53:41.991 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1 | 1:C 05 Jan 2021 15:53:41.991 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1 | 1:C 05 Jan 2021 15:53:41.991 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | 1:M 05 Jan 2021 15:53:41.993 * Running mode=standalone, port=6379.
redis_1 | 1:M 05 Jan 2021 15:53:41.994 # Server initialized
redis_1 | 1:M 05 Jan 2021 15:53:41.995 * 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)
web_1 | 172.20.0.1 - - [05/Jan/2021 15:53:58] "GET / HTTP/1.1" 200 -
web_1 | 172.20.0.1 - - [05/Jan/2021 15:53:59] "GET /favicon.ico HTTP/1.1" 404 -
web_1 | 172.20.0.1 - - [05/Jan/2021 15:54:01] "GET / HTTP/1.1" 200 -
chenshifengdeMacBook-Pro:docker-compose chenshifeng$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------
docker-compose_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
docker-compose_web_1 flask run Up 0.0.0.0:5000->5000/tcp
chenshifengdeMacBook-Pro:docker-compose chenshifeng$ docker-compose top
docker-compose_redis_1
PID USER TIME COMMAND
----------------------------------
17626 999 0:03 redis-server
docker-compose_web_1
PID USER TIME COMMAND
----------------------------------------------------------------------------
17732 root 0:00 {flask} /usr/local/bin/python /usr/local/bin/flask run