# Docker Compose-容器单机编排

在实际生产或者项目中使用 Docker 容器时,往往不是一个容器就能满足需求的。

比如对于一个常规的 Web 应用而言,前后端,数据库均需要独立的容器,这个时候便非常需要进行容器的 “编排” 了。

Docker 为我们提供了一个工具 docker-compose,可用于 单个机器上的 Docker 容器编排

它允许⽤户通过⼀个单独的 docker-compose.yml 模板⽂件(YAML 格式)来定义⼀组相关联的应⽤容器为⼀个项⽬(project)。

# Docker Compose

  • Docker Compose 是用于定义和运行多容器Docker应用程序的工具
  • Docker Compose 可以通过一个 docker-compose.yml 文件定义多容器的 Docker 应用
  • 通过一条命令就可以根据 docker-compose.yml 文件的定义去创建和管理这多个容器

Compose 中有三个重要的概念:

  • Services(服务)
  • Networks(网络)
  • Volumes(数据卷)

# Services(服务)

一个 Service 代表⼀个应⽤的容器。可以通过 docker hub 的镜像或本地 dockerfile 构建的镜像进行创建。

Service 的启动类似于 docker run 运行一个容器。运行容器时,可以给其指定 networkvolume。所以我们可以给 Service 指定 networkvolume 的引用。

# Networks(网络)

定义整个应用中的 networks,被 services 中的服务引用。

# Volumes(数据卷)

定义整个应用中的 volumes,被 services 中的服务引用。

# 案例说明

version: '3' # 定义compose版本

services:

  wordpress:
    image: wordpress # 指定镜像
    ports:
      - 8080:80 # 端口映射
    depends_on: # 表达服务之间的依赖性
      - mysql
    environment: # 指定环境变量
      WORDPRESS_DB_HOST: mysql #连接数据库的地址,必须要用依赖的服务的名字
      WORDPRESS_DB_PASSWORD: root # 自定义的连接数据库的密码,需要和下面的mysql设置的要一致
    networks:
      - my-bridge # 引用 networks 中定义的 bridge 网络

  mysql:
    image: mysql:5.7 # 指定镜像
    environment: # 指定环境变量
      MYSQL_ROOT_PASSWORD: root # 指定数据库登录密码
      MYSQL_DATABASE: wordpress # 指定数据库名
    volumes:
      - mysql-data:/var/lib/mysql # 绑定数据卷实现数据共享与持久化
    networks:
      - my-bridge # 引用 networks 中定义的 bridge 网络

volumes:
  mysql-data: # 创建⼀个数据卷

networks:
  my-bridge:
    driver: bridge # 创建一个名称为 my-bridge,类型为 bridge 的网络

每个 docker-compose.yml 都需要包含一个 version 的配置,这个 version 表示 docker-compose 配置文件格式的版本,不同的版本会影响到与 Docker 版本的兼容性。

# 安装

Compose ⽀持 LinuxmacOSWindows 10 三⼤平台。Compose 可以通过 Python 的包管理⼯具 pip 进⾏安装,也可以直接下载编译好的⼆进制⽂件使⽤,甚⾄能够直接在 Docker 容器中运⾏。

前两种⽅式是传统⽅式,适合本地环境下安装使⽤;最后⼀种⽅式则 不破坏系统环境,更适合 云计算场景

Docker for MacDocker for Windows ⾃带 docker-compose ⼆进制⽂件,安装 Docker 之后可以直接使⽤。

# 二进制安装

在Linux上,您可以从官方 GitHub Release 处直接下载编译好的⼆进制⽂件即可。

运行以下命令以下载 Docker Compose 的当前稳定版本:

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

可执行权限 应用于二进制文件:

$ sudo chmod +x /usr/local/bin/docker-compose 

# PIP 安装

注: x86_64 架构的 Linux 建议按照上边的⽅法下载⼆进制包进⾏安装,如果您计算机的架构是ARM (例如,树莓派),再使⽤ pip 安装。

Docker Compose 是一个由 Python 编写的软件,在拥有 Python 运行环境的机器上,我们可以直接运行它,不需要其它的操作。

我们也能够通过 Python 的包管理工具 pip 来安装 Docker Compose

$ sudo pip install  docker-compose

# 容器中执⾏

sudo curl -L --fail https://github.com/docker/compose/releases/download/1.26.2/run.sh -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# 安装补全工具

为了方便我们输入命令,也可以安装 Docker 的补全提示工具帮忙我们快速输入命令

# 卸载

如果是二进制包方式安装的,删除二进制⽂件即可。

$ sudo rm /usr/local/bin/docker-compose

如果是通过 pip 安装的,则执⾏如下命令即可删除。

$ sudo pip uninstall docker-compose

如果是在容器中安装,直接删除容器即可。

# 快速上手

使用 Compose 基本上包括三个步骤:

  • 使用 Dockerfile 定义应用程序的环境。
  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

下面我们用 Python 来建⽴⼀个能够记录页面访问次数的 web ⽹站。 新建⽂件夹,在该⽬录中编写 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)

接着编写 Dockerfile ⽂件,内容为:

FROM python:3.6-alpine
ADD . /code
WORKDIR /code
RUN pip install redis flask
CMD ["python", "app.py"]

然后是编写 docker-compose.yml ⽂件。

version: '3'
services:
  web:
    build: . # 使用从当前目录中的Dockerfile构建的镜像
    ports:
      - "5000:5000" # 端口映射
    volumes:
      - .:/code # 将当前目录挂载到容器的/code目录,从而使您可以即时修改代码,而不必重建镜像
  redis:
    image: "redis:alpine"

运行 compose 项⽬:

$ docker-compose up

此时访问本地 5000 端⼝,每次刷新页面,计数就会加 1。

# docker-compose.yml 模板文件常用配置选项

# version

指定本 yml 依从的 compose 哪个版本制定的。

# build

在构建时应用的配置选项,Compose 会利用它自动构建镜像,然后启动服务容器。该值可以是一个路径,

version: "3.7"
services:
  webapp:
    build: ./dir

或者,也可以是一个对象,用于指定 Dockerfile 参数:

version: "3.7"
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1
      labels:
        - "com.example.description=Accounting webapp"
        - "com.example.department=Finance"
        - "com.example.label-with-empty-value"
      target: prod
  • context:上下文路径。
  • dockerfile:指定构建镜像的 Dockerfile 文件名。
  • args:添加构建参数,这是只能在构建过程中访问的环境变量。
  • labels:设置构建镜像的标签。
  • target:定义构建指定的阶段。有关详细信息,请参见多阶段构建文档。

# command

覆盖容器启动后默认执行的命令。

# 方式1
command: bundle exec thin -p 3000
# 方式2
command: [bundle, exec, thin, -p, 3000]

# container_name

自定义容器名称,而不是使用默认生成的名称。

container_name: my-web-container

# depends_on

在使用Compose时,最大的好处就是减少少打启动命令,但一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。例如在没启动数据库容器的时候启动应用容器,应用容器会因为找不到数据库而退出。

depends_on 标签用于解决容器的依赖、启动先后的问题。

  • docker-compose up :以依赖性顺序启动服务。在以下示例中,先启动 db 和 redis ,才会启动 web。
  • docker-compose up SERVICE :自动包含 SERVICE 的依赖项。在以下示例中,docker-compose up web 还将创建并启动 db 和 redis。
  • docker-compose stop :按依赖关系顺序停止服务。在以下示例中,web 在 db 和 redis 之前停止。
version: "3.8"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

注意:web 服务不会等待 redis db 完全启动 之后才启动。

在以docker stack deploy方式,基于 version 3 版本部署时,将忽略depends_on选项。

# env_file

从文件中添加环境变量。

env_file: .env

也可以是列表格式:

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

# environment

添加环境变量。您可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保 YML 解析器不会将其转换为 True 或 False。

environment 部分中声明的环境变量将覆盖 env_file 中申明的这些值。

environment:
  RACK_ENV: development
  SHOW: 'true'

# expose

公开端口,但是不将其映射到宿主机。只允许能被连接的服务访问。只能指定内部端口。

expose:
  - "3000"
  - "8000"

# extra_hosts

添加主机名映射。类似 docker client --add-host

extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

以上会在此服务的内部容器中 /etc/hosts 创建一个具有 ip 地址和主机名的映射关系:

162.242.195.82  somehost
50.31.209.229   otherhost

# healthcheck

对 docker 服务是否健康运行进行检测。

有关运行状况检查如何工作的详细信息,请参阅HEALTHCHECK Dockerfile instruction

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
  interval: 1m30s # 设置检测间隔
  timeout: 10s # 设置检测超时时间
  retries: 3 # 设置重试次数
  start_period: 40s # 启动后,多少秒开始启动检测程序

# image

指定容器运行的镜像。以下格式都可以:

image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id

# logging

对服务的日志记录进行配置。

driver:指定服务容器的日志记录驱动程序,默认值为 json-file。有以下三个选项

  • driver: "json-file"
  • driver: "syslog"
  • driver: "none"

默认驱动程序 json-file 具有限制存储日志量的选项,可以使用以下参数,限制日志的数量和大小。

logging:
  driver: json-file
  options:
    max-size: "200k" # 单个文件大小为200k
    max-file: "10" # 最多10个文件

当达到文件限制上限,会自动删除旧的文件。

驱动程序为 syslog 时,可以使用 syslog-address 指定日志接收地址。

logging: driver: syslog options: syslog-address: "tcp://192.168.0.42:123"

# network_mode

设置网络模式。

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

# networks

配置容器连接的网络,引用 services 同级目录 networks 下的条目 。

ervices:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2
networks:
  some-network:
    # 使用自定义驱动程序
    driver: custom-driver-1
  other-network:
    # 使用需要特殊选项的自定义驱动程序
    driver: custom-driver-2

aliases :同一网络上的其他容器可以使用服务名称或此别名来连接到对应容器的服务。

# restart

  • no:是默认的重启策略,在任何情况下都不会重启容器。
  • always:容器总是重新启动。
  • on-failure:在容器非正常退出时(退出状态非0),才会重启容器。
  • unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

注:swarm 集群模式,请改用 restart_policy。

# secrets

存储敏感数据,例如密码:

version: "3.1"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
  secrets:
    - my_secret

secrets:
  my_secret:
    file: ./my_secret.txt

# volumes

将主机的 数据卷主机⽬录 挂载到容器里。

实现 数据共享持久化

version: "3.7"
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "/localhost/data:/var/lib/postgresql/data"

# Compose 常用命令

docker-compose 命令的基本的使⽤格式是:

docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]

命令选项:

    • -f, --file FILE 指定使⽤的 Compose 模板⽂件,默认为 docker-compose.yml,可以多次指定。
  • -p, --project-name NAME 指定项⽬名称,默认将使⽤所在⽬录名称作为项⽬名。
  • --x-networking 使⽤ Docker 的可拔插⽹络后端特性
  • --x-network-driver DRIVER 指定⽹络后端的驱动,默认为 bridge
  • --verbose 输出更多调试信息。
  • -v, --version 打印版本并退出。

# up

格式为 docker-compose up [options] [SERVICE...],该命令⼗分强⼤,它将尝试⾃动完成包括 构建镜像(重新)创建服务启动服务,并 关联服务相关容器 的⼀系列操作。

连接的服务都将会被⾃动启动,除⾮已经处于运⾏状态。 可以说,⼤部分时候都可以直接通过该命令来启动⼀个项⽬。

默认情况,docker-compose up 启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很⽅便进⾏调试。 当通过 Ctrl-C 停⽌命令时,所有容器将会停⽌。

如果使⽤ docker-compose up -d ,将会在后台启动并运⾏所有的容器。⼀般推荐 ⽣产环境下使⽤该选项。

默认情况,如果服务容器已经存在, docker-compose up 将会尝试停⽌容器,然后重新创建(保持使⽤ volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml ⽂件的最新内容。

如果⽤户不希望容器被停⽌并重新创建,可以使⽤ docker-compose up --no-recreate 。这样将只会启动处于停⽌状态的容器,⽽忽略已经运⾏的服务。

如果⽤户只想重新部署某个服务,可以使⽤ docker-compose up --no-deps -d <SERVICE_NAME> 来重新创建服务并后台停⽌旧服务,启动新服务,并不会影响到其所依赖的服务。

选项:

  • -d 在后台运⾏服务容器。
  • --no-color 不使⽤颜⾊来区分不同的服务的控制台输出。
  • --no-deps 不启动服务所链接的容器。
  • --force-recreate 强制重新创建容器,不能与 --no-recreate 同时使⽤。
  • --no-recreate 如果容器已经存在了,则不重新创建,不能与 --force-recreate 同时使⽤。
  • --no-build 不⾃动构建缺失的服务镜像。
  • -t, --timeout TIMEOUT 停⽌容器时候的超时(默认为 10 秒)。

# start

格式为 docker-compose start [SERVICE...],启动已经存在的服务容器。

# stop

格式为 docker-compose stop [options] [SERVICE...],停⽌已经处于运⾏状态的容器,但不删除它。

通过 docker-compose start 可以再次启动这些容器。

# down

此命令将会停⽌ up 命令所启动的容器,并移除⽹络

# build

build 格式为 docker-compose build [options] [SERVICE...]

构建(重新构建)项⽬中的服务容器。服务容器⼀旦构建后,将会带上⼀个标记名,例如对于 web 项⽬中的⼀个 db 容器,可能是 web_db。

可以随时在项⽬⽬录下运⾏ docker-compose build 来重新构建服务。选项包括:

  • --force-rm 删除构建过程中的临时容器。
  • --no-cache 构建镜像过程中不使⽤ cache(这将加⻓构建过程)。
  • --pull 始终尝试通过 pull 来获取更新版本的镜像。

# config

验证 Compose ⽂件格式是否正确,若正确则显示配置,若格式错误显示错误原因。

# exec

进⼊指定的容器。

# help

获得⼀个命令的帮助。

# images

列出 Compose ⽂件中包含的镜像。

# kill

格式为 docker-compose kill [options] [SERVICE...]

通过发送 SIGKILL 信号来 强制停⽌服务容器。⽀持通过 -s 参数来指定发送的信号,例如通过如下指令发送 SIGINT 信号。

$ docker-compose kill -s SIGINT

# logs

格式为 docker-compose logs [options] [SERVICE...],查看服务容器的输出。默认情况下,docker-compose 将对不同的服务输出使⽤不同的颜⾊来区分。

可以通过 --no-color 来关闭颜⾊。该命令在调试问题的时候⼗分有⽤。

# pause

格式为 docker-compose pause [SERVICE...],暂停⼀个服务容器。

# port

格式为 docker-compose port [options] SERVICE PRIVATE_PORT,打印某个容器端⼝所映射的公共端⼝。选项:

  • --protocol=proto 指定端⼝协议,tcp(默认值)或者 udp。
  • --index=index 如果同⼀服务存在多个容器,指定命令对象容器的序号(默认为 1)。

# ps

格式为 docker-compose ps [options] [SERVICE...],列出项⽬中⽬前的所有容器。选项:

  • -q 只打印容器的 ID 信息。

# pull

格式为 docker-compose pull [options] [SERVICE...],拉取服务依赖的镜像。选项:

  • --ignore-pull-failures 忽略拉取镜像过程中的错误。 push:推送服务依赖的镜像到 Docker 镜像仓库。

# push

推送服务依赖的镜像到 Docker 镜像仓库。

# restart

格式为 docker-compose restart [options] [SERVICE...],重启项⽬中的服务。选项:

  • -t, --timeout TIMEOUT 指定重启前停⽌容器的超时(默认为 10 秒)。

# rm

格式为 docker-compose rm [options] [SERVICE...],删除所有(停⽌状态的)服务容器。

推荐先执行 docker-compose stop 命令来停⽌容器。

选项:

  • -f, --force 强制直接删除,包括⾮停⽌状态的容器。⼀般尽量不要使⽤该选项。
  • -v 删除容器所挂载的数据卷。

# run

格式为 docker-compose run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...],在指定服务上执⾏⼀个命令。例如:

$ docker-compose run ubuntu ping docker.com

将会启动⼀个 ubuntu 服务容器,并执⾏ ping docker.com 命令。默认情况下,如果存在关联,则所有关联的服务将会⾃动被启动,除⾮这些服务已经在运⾏中。

该命令类似启动容器后运⾏指定的命令,相关卷、链接等等都将会按照配置⾃动创建。

给定命令将会覆盖原有的⾃动运⾏命令; 不会⾃动创建端⼝,以避免冲突。

如果不希望⾃动启动关联的容器,可以使⽤ --no-deps 选项,例如:

$ docker-compose run --no-deps web python manage.py shell

将不会启动 web 容器所关联的其它容器,选项:

  • -d 后台运⾏容器。
  • --name NAME 为容器指定⼀个名字。
  • --entrypoint CMD 覆盖默认的容器启动指令。
  • -e KEY=VAL 设置环境变量值,可多次使⽤选项来设置多个环境变量。
  • -u, --user="" 指定运⾏容器的⽤户名或者 uid。
  • --no-deps 不⾃动启动关联的服务容器。
  • --rm 运⾏命令后⾃动删除容器,d 模式下将忽略。
  • -p, --publish=[] 映射容器端⼝到本地主机。
  • --service-ports 配置服务端⼝并映射到本地主机。
  • -T 不分配伪 tty,意味着依赖 tty 的指令将⽆法运⾏。

# scale

格式为 docker-compose scale [options] [SERVICE=NUM...],设置指定服务运⾏的容器个数。用于实现 水平扩展。通过 service=num 的参数来设置数量。例如:

$ docker-compose scale web=3 db=2

将启动 3 个容器运⾏ web 服务,2 个容器运⾏ db 服务。

⼀般情况下,当指定数⽬多于该服务当前实际运⾏容器,将新创建并启动容器;反之,将停⽌容器。选项:

  • -t, --timeout TIMEOUT 停⽌容器时候的超时(默认为 10 秒)。

选项:

  • -t, --timeout TIMEOUT 停⽌容器时候的超时(默认为 10 秒)。

# top

查看各个服务容器内运⾏的进程。

# unpause

格式为 docker-compose unpause [SERVICE...],恢复处于暂停状态中的服务。

# 参考

更新时间: 8/1/2020, 3:36:37 AM