阅读 43

Docker Compose概述

Compose 是一个定义和运行多容器的Docker程序。使用Compose,你可以使用一个YAML文件配置你的服务,然后,通过一个简单的命令,可以创建并启动所有的服务。

Compose 可以以下所有环境中工作:production, staging, development, testing, 还有 CI workflows.

Compose 典型的使用方式:

  • 通过Dockerfile定义app运行环境
  • docker-compose.yml中定义组成app的所有服务,以使他们可以在一个隔离的环境一起运行
  • 运行docker-compose up,使Compose启动并运行整个app

一个docker-compose.yml长得如下文件:

version: '3'
services:
  web:
    build: .
    ports:
    - "5000:5000"
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
复制代码

Compose具有用于管理应用程序整个生命周期的命令:

  • 启动,停止和重建服务
  • 查看正在运行的服务的状态
  • 流式传输正在运行的服务的日志输出
  • 对服务运行一次性命令

功能

使Compose有效的功能包括:

单个主机上的多个隔离环境

Compose使用项目名称将环境彼此隔离。 您可以在几个不同的上下文中使用此项目名称:

  • 在一个dev主机上,创建单个环境的多个副本,例如您希望为项目的每个特性分支运行一个稳定的副本
  • 在CI服务器上,为了防止构建相互干扰,可以将项目名称设置为惟一的构建编号
  • 在共享主机或dev主机上,防止可能使用相同服务名称的不同项目相互干扰

默认项目名称是项目目录的基本名称。 您可以使用-p命令行选项或COMPOSE_PROJECT_NAME环境变量来设置自定义项目名称。

创建容器时保留卷数据

Compose保留服务使用的所有卷。 当docker-compose up运行时,如果它从以前的运行中找到了任何容器,则会将卷从旧容器复制到新容器。 此过程可确保您在卷中创建的所有数据均不会丢失。

如果在Windows计算机上使用docker-compose,请参阅环境变量并根据您的特定需求调整必要的环境变量。

仅重新创建已更改的容器

Compose缓存用于创建容器的配置。 重新启动未更改的服务时,Compose会重新使用现有容器。 重复使用容器意味着您可以快速更改环境。

变量和环境之间的合成移动

Compose支持Compose文件中的变量。 您可以使用这些变量针对不同的环境或不同的用户自定义合成。

您可以使用extends字段或通过创建多个Compose文件来扩展Compose文件。

常见用例

Compose可以以多种不同方式使用。 下面概述了一些常见的用例。

开发环境

在开发软件时,在独立的环境中运行应用程序并与之交互的能力至关重要。 Compose命令行工具可用于创建环境并与之交互。

Compose文件提供了一种记录和配置应用程序的所有服务依赖项(数据库,队列,缓存,Web服务API等)的方式。 使用Compose命令行工具,您可以使用单个命令(docker-compose up)为每个依赖关系创建和启动一个或多个容器。

这些功能一起为开发人员提供了一种方便的方式来开始项目。 Compose可以将多页的“开发人员入门指南”简化为单个机器可读的Compose文件和一些命令。

自动测试环境

自动测试套件是任何持续部署或持续集成过程的重要组成部分。 自动化的端到端测试需要在其中运行测试的环境。 Compose提供了一种方便的方法来为您的测试套件创建和销毁隔离的测试环境。 通过在Compose文件中定义完整的环境,您只需几个命令即可创建和销毁这些环境:

$ docker-compose up -d
$ ./run_tests
$ docker-compose down
复制代码

单机部署

传统上,Compose一直专注于开发和测试工作流程,但是在每个版本中,我们都在面向生产的更多功能方面取得了进展。 您可以使用Compose部署到远程Docker Engine。 Docker Engine可以是配备有Docker Machine的单个实例,也可以是整个Docker Swarm集群。

Docker Compose 安装

您可以在macOS,Windows和64位Linux上运行Compose。

Docker Compose依靠Docker Engine进行有意义的工作,因此请确保根据您的设置在本地或远程安装Docker Engine。

  • 在Mac和Windows的Docker桌面等桌面系统上,这些桌面安装中包含Docker Compose。
  • 在Linux系统上,首先按照Get Docker页面上的描述为您的操作系统安装Docker,然后回到这里获得在Linux系统上安装Compose的说明。
  • 要以非根用户的身份运行撰写,请参阅以非根用户的身份管理Docker。

安装Compose

请按照以下说明在Mac,Windows,Windows Server 2016或Linux系统上安装Compose,或查找其他替代方法,例如使用pip Python软件包管理器或将Compose作为容器安装。

因为Mac和Windows的Docker桌面已经包含了Compose,所以无需额外操作,在Linux上,需要单独安装Compose

  • 运行此命令下载Docker Compose的当前稳定版本
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
复制代码
  • 将可执行权限应用于二进制文件:
sudo chmod +x /usr/local/bin/docker-compose
复制代码

卸载Compose

如果你是使用curl安装的Compose,使用下面的命令

sudo rm /usr/local/bin/docker-compose
复制代码

如果是使用的pip安装的Compose,使用下面的命令:

pip uninstall docker-compose
复制代码

案例

在此页面上,您将构建一个运行在Docker Compose上的简单Python Web应用程序。 该应用程序使用Flask框架,并在Redis中维护一个计数器。 尽管示例使用Python,但即使您不熟悉此处演示的概念,也应可以理解。

准备

确保已安装Docker Engine和Docker Compose。 您不需要安装Python或Redis,因为两者均由Docker镜像提供。

步骤一:组织

定义应用程序依赖项。

  • 为项目创建目录:
$ mkdir composetest
$ cd composetest
复制代码
  • 在项目目录中创建一个名为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)
复制代码

在此示例中,redis是应用程序网络上的redis容器的主机名。 我们为Redis使用默认端口6379

  • 在项目目录中创建另一个名为requirements.txt的文件,并将其粘贴进来
flask
redis
复制代码

步骤二:创建一个Dockerfile

在此步骤中,您将编写一个构建Docker映像的Dockerfile。 该图像包含Python应用程序所需的所有依赖关系,包括Python本身。

在您的项目目录中,创建一个名为Dockerfile的文件并粘贴以下内容:

FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]
复制代码

步骤三:在Compose文件中定义服务

在项目目录中创建一个名为docker-compose.yml的文件,然后粘贴以下内容:

version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"
复制代码

该Compose文件定义了两个服务:webredis

web服务使用当前目录中的Dockerfile构建的映像。然后,它将容器和主机绑定到暴露的端口5000。此示例服务使用Flask web服务器的默认端口5000。Redis服务使用从Docker Hub仓库中提取的公共Redis镜像。

步骤四:使用Compose构建和运行您的应用

在项目目录中,通过运行docker-compose up来启动应用程序。

$ docker-compose up
Creating network "composetest_default" with the default driver
Creating composetest_web_1 ...
Creating composetest_redis_1 ...
Creating composetest_web_1
Creating composetest_redis_1 ... done
Attaching to composetest_web_1, composetest_redis_1
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
redis_1  | 1:C 17 Aug 22:11:10.480 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 17 Aug 22:11:10.480 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 17 Aug 22:11:10.480 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
web_1    |  * Restarting with stat
redis_1  | 1:M 17 Aug 22:11:10.483 * Running mode=standalone, port=6379.
redis_1  | 1:M 17 Aug 22:11:10.483 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
web_1    |  * Debugger is active!
redis_1  | 1:M 17 Aug 22:11:10.483 # Server initialized
redis_1  | 1:M 17 Aug 22:11:10.483 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
web_1    |  * Debugger PIN: 330-787-903
redis_1  | 1:M 17 Aug 22:11:10.483 * Ready to accept connections
复制代码

Compose提取Redis映像,为您的代码构建映像,然后启动您定义的服务。 在这种情况下,代码会在构建时静态复制到映像中。

在浏览器中输入http://localhost:5000/以查看该应用程序正在运行。

如果您在Linux,Mac上的Docker Desktop或Windows上的Docker Desktop上本地使用Docker,则该网络应用现在应该在Docker守护程序主机上的端口5000上侦听。 将您的Web浏览器指向http://localhost:5000/以查找Hello World消息。 如果仍然无法解析,您也可以尝试http://127.0.0.1:5000

如果您在Mac或Windows上使用Docker Machine,请使用docker-machine ip MACHINE_VM获取Docker主机的IP地址。 然后,在浏览器中打开http:// MACHINE_VM_IP:5000

您应该在浏览器中看到一条消息,内容为:

Hello World! I have been seen 1 times.
复制代码

刷新页面,数字就会增加:

Hello World! I have been seen 2 times.
复制代码

切换到另一个终端窗口,然后键入docker image ls列出本地图像。

$ docker image ls
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
composetest_web         latest              e2c21aa48cc1        4 minutes ago       93.8MB
python                  3.4-alpine          84e6077c7ab6        7 days ago          82.5MB
redis                   alpine              9d8fa9aa0e5b        3 weeks ago         27.5MB

复制代码

通过从第二个终端的项目目录中运行docker-compose down或在启动该应用的原始终端中按CTRL + C来停止该应用。

步骤五:编辑Compose文件以添加绑定挂载

在项目目录中编辑docker-compose.yml以添加Web服务的绑定挂载:

version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
    environment:
      FLASK_ENV: development
  redis:
    image: "redis:alpine"
复制代码

新的volumes键挂载主机上的程序目录(当前目录)到容器内的/code目录,从而使您可以即时修改代码,而不必重建映像。 环境变量键设置FLASK_ENV环境变量,该变量告诉flask run在开发模式下运行,并在代码更改时重新加载代码。 此模式仅应在开发中使用。

步骤六:使用Compose重建并运行应用程序

在项目目录中,键入docker-compose up以使用更新的Compose文件构建应用程序,然后运行它。

$ docker-compose up
Creating network "composetest_default" with the default driver
Creating composetest_web_1 ...
Creating composetest_redis_1 ...
Creating composetest_web_1
Creating composetest_redis_1 ... done
Attaching to composetest_web_1, composetest_redis_1
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
...
复制代码

再次在网络浏览器中检查Hello World消息,然后刷新以查看计数增量。

步骤七:更新应用程序

因为现在应用程序代码是使用卷安装到容器中的,所以您可以对其代码进行更改并立即查看更改,而无需重建映像。

更改app.py文件中的问候语,例如更改Hello World!Hello from Docker!:

return 'Hello from Docker! I have been seen {} times.\n'.format(count)
复制代码

在浏览器中刷新应用。 问候语应更新,并且计数器应仍在增加。

步骤八:尝试使用其他一些命令

如果要在后台运行服务,则可以将-d标志(用于“分离”模式)传递给docker-compose up并使用docker-compose ps来查看当前正在运行的内容:

$ docker-compose up -d
Starting composetest_redis_1...
Starting composetest_web_1...

$ docker-compose ps
Name                 Command            State       Ports
-------------------------------------------------------------------
composetest_redis_1   /usr/local/bin/run         Up
composetest_web_1     /bin/sh -c python app.py   Up      5000->5000/tcp
复制代码

docker-compose run命令允许您为服务运行一次性命令。 例如,查看哪些环境变量可用于web服务:

$ docker-compose run web env
复制代码

请参阅docker-compose --help来查看其他可用命令。 您还可以为bashzsh shell安装命令完成功能,这还将显示可用的命令。

如果您使用docker-compose up -d启动了Compose,请在完成服务后停止它们:

$ docker-compose stop
复制代码

您可以使用down命令来删除所有内容,--volumes,还要删除Redis容器使用的数据卷

$ docker-compose down --volumes
复制代码

至此,您已经了解了Compose的工作原理。