目录

    1. 基本概念

    Docker Compose 是一个用来定义和运行复杂应用的 Docker 工具。使用 Docker Compose,可以在一个文件中定义一个多容器应用,然后使用一条命令来启动你的应用,完成一切准备工作。

    Docker Compose 定位是 ‘defining and running complex applications with Docker’,前身是 Fig,兼容 Fig 的模板文件。

    Docker Compose 发展至今,有 Version 1、Version 2、Version 3 三个大版本。如果不声明版本,默认为 Version 1。Version 1 不能使用 volumes,、networks、 build参数。Version 2,必须在版本中申明,所有的服务,都必须申明在 service 关键字下。Version 3 删除了 volume_drivervolumes_fromcpu_sharescpu_quotacpusetmem_limitmemswap_limitextendsgroup_add 关键字,新增了 deploy,全面支持 Swarm mode。更详细的比较可以查看参考链接。

    本文中主要以 Version 2 为例学习 Docker Compose 容器的编排。

    2. 工作原理

    Docker Compose 将所管理的容器分为三层,工程(project),服务(service)以及容器(contaienr)。Docker Compose 运行的目录下的所有文件(docker-compose.yml、extends文件、环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。

    一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖。一个服务当中可包括多个容器实例,Docker Compose 并没有解决负载均衡的问题,因此需要借助其他工具实现服务发现及负载均衡。

    Docker Compose 的工程配置文件默认为 docker-compose.yml,可通过环境变量 COMPOSE_FILE 或 -f 参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。以下是一个简单的配置文件:

    version: '2'
    services:
        web:
            build: .
            ports:
              - "80:90"
            volumes:
              - .:/code
            links:
              - redis
        redis:
            image: redis
    

    其定义了两个服务 web 和 redis。web 服务的镜像需要使用当前目录的 Dockerfile 实时构建,其容器运行时需要在宿主机开放端口 80 并映射到容器端口 90 ,并且挂载存储卷 /code 以及关联服务 redis。redis 服务通过镜像 redis 启动。

    Docker Compose 是由 Python 语言实现的,它通过调用 docker-py 库(可参考 https://github.com/docker/docker-py )与 docker engine 通信实现构建 docker 镜像,启动停止 docker 容器等。Docker-py 库调用 docker remote API(可参考 https://docs.docker.com/reference/api/docker_remote_api/ )与 Docker Daemon 通信,可通过 DOCKER_HOST 配置本地或远程 Docker Daemon 的地址。

    3 Docker Compose 常用命令

    命令解释
    docker-compose build构建 yml 中服务的镜像
    docker-compose ps查看已经启动的服务状态
    docker-compose kill停止某个服务
    docker-compose logs可以查看某个服务的log
    docker-compose port打印绑定的public port
    docker-compose pullpull服务镜像
    docker-compose up启动yml定义的所有服务
    docker-compose stop停止yml中定义的所有服务
    docker-compose start启动被停止的yml中的所有服务
    docker-compose kill强行停止yml中定义的所有服务
    docker-compose rm删除yml中定义的所有服务
    docker-compose restart重启yml中定义的所有服务
    docker-compose scale扩展某个服务的个数,可以向上或向下
    docker-compose version查看compose的版本

    4. YAML 常用关键字

    4.1 build

    指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径)。 Compose 将会利用它自动构建这个镜像,然后使用这个镜像。

    build: /path/to/build/dir
    

    4.2 command

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

    command: echo "hello world"
    

    4.3 dockerfile

    如果需要指定额外的编译镜像的 Dockefile 文件,可以通过该指令来指定。例如:

    dockerfile: Dockerfile-alternate
    

    注意,该指令不能跟 image 同时使用,否则 Compose 将不知道根据哪个指令来生成最终的服务镜像。

    4.4 env_file

    从文件中获取环境变量,可以为单独的文件路径或列表。

    如果通过 docker-compose -f FILE 方式来指定 Compose 模板文件,则 env_file 中变量的路径会基于模板文件路径。

    如果有变量名称与 environment 指令冲突,则按照惯例,以后者为准。

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

    环境变量文件中每一行必须符合格式,支持 # 开头的注释行。

    # common.env: Set development environment
    PROG_ENV=development
    

    4.5 environment

    设置环境变量。你可以使用数组或字典两种格式。

    只给定名称的变量会自动获取运行 Compose 主机上对应变量的值,可以用来防止泄露不必要的数据。例如:

    environment:
      RACK_ENV: development
      SESSION_SECRET:
    

    或者

    environment:
      - RACK_ENV=development
      - SESSION_SECRET
    

    注意,如果变量名称或者值中用到 true|false,yes|no 等表达布尔含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义。

    http://yaml.org/type/bool.html 中给出了这些特定词汇,包括

     y|Y|yes|Yes|YES|n|N|no|No|NO
    |true|True|TRUE|false|False|FALSE
    |on|On|ON|off|Off|OFF
    

    4.6 expose

    暴露端口,但不映射到宿主机,只被连接的服务访问。仅可以指定内部端口为参数

    expose:
     - "3000"
     - "8000"
    

    4.7 image

    指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。例如:

    image: ubuntu
    image: orchardup/postgresql
    image: a4bc65fd
    

    链接到其它服务中的容器。使用服务名称(同时作为别名)或服务名称:服务别名 (SERVICE:ALIAS) 格式都可以。

    links:
     - db
     - db:database
     - redis
    

    使用的别名将会自动在服务容器中的 /etc/hosts 里创建。例如:

    172.17.2.186  db
    172.17.2.186  database
    172.17.2.187  redis
    

    被链接容器中相应的环境变量也将被创建。

    4.9 volumes

    数据卷所挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)。该指令中路径支持相对路径。例如

    volumes:
     - /var/lib/mysql
     - cache/:/tmp/cache
     - ~/configs:/etc/configs/:ro
    

    4.10 volumes_from

    从另一个服务或容器挂载它的数据卷。

    volumes_from:
     - service_name
     - container_name
    

    5. 参考