Docker Compose

Docker Compose 能够在 Docker 节点上,以单引擎模式(Single-Engine Mode)进行多容器应用的部署和管理。

多数的现代应用通过多个更小的服务互相协同来组成一个完整可用的应用。比如一个简单的示例应用可能由如下 4 个服务组成。

    Web前端。
    订单管理。
    品类管理。
    后台数据库。
将以上服务组织在一起,就是一个可用的应用。

部署和管理繁多的服务是困难的,这正是 Docker Compose 要解决的问题。

Docker Compose 并不是通过脚本和各种冗长的 docker 命令来将应用组件组织起来,而是通过一个声明式的配置文件描述整个应用,从而使用一条命令完成部署。

应用部署成功后,还可以通过一系列简单的命令实现对其完整声明周期的管理。配置文件还可以置于版本控制系统中进行存储和管理。
Docker Compose 的背景
Docker Compose 的前身是 Fig。Fig 是一个由 Orchard 公司开发的强有力的工具,在当时是进行多容器管理的最佳方案。Fig 是一个基于 Docker 的 Python 工具,允许用户基于一个 YAML 文件定义多容器应用,从而可以使用 fig 命令行工具进行应用的部署。Fig 还可以对应用的全生命周期进行管理。内部实现上,Fig 会解析 YAML 文件,并通过 Docker API 进行应用的部署和管理。

在 2014 年,Docker 公司收购了 Orchard 公司,并将 Fig 更名为 Docker Compose。命令行工具也从 fig 更名为 docker-compose,并自此成为绑定在 Docker 引擎之上的外部工具。

虽然它从未完全集成到 Docker 引擎中,但是仍然受到广泛关注并得到普遍使用。

直至今日,Docker Compose 仍然是一个需要在 Docker 主机上进行安装的外部 Python 工具。

使用它时,首先编写定义多容器(多服务)应用的 YAML 文件,然后将其交由 docker-compose 命令处理,Docker Compose 就会基于 Docker 引擎 API 完成应用的部署。

Docker Compose在Linux的安装

在 Linux 上安装 Docker Compose分为两步。

首先使用 curl 命令下载二进制文件,然后使用 chmod 命令将其置为可运行。

Docker Compose 在 Linux 上的使用,同样需要先安装有 Docker 引擎。

如下命令会下载 1.24.1 版本的 Docker Compose 到 //usr/local/bin/docker-compose。请在 GitHub 上查找想安装的版本(https://github.com/docker/compose/releases),并替换 URL 中的 1.24.1。

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose


下载 docker-compose 二进制文件后,使用如下命令使其可执行。

sudo chmod +x /usr/local/bin/docker-compose
检查安装情况以及版本。

$ docker-compose --version

现在就可以在 Linux 上使用 Docker Compose 了。上图中第一次安装完查看版本的时候报错,是因为没有下载完整,重新使用下载命令执行后,再执行安装命令就成功了。

yml配置文件及常用指令简介

Docker Compose 使用 YAML 文件来定义多服务的应用。YAML 是 JSON 的一个子集,因此也可以使用 JSON。Docker Compose 默认使用文件名 docker-compose.yml。也可以使用 -f 参数指定具体文件。

如下是一个简单的 Compose 文件的示例,它定义了一个包含两个服务(web-fe 和 redis)的小型 Flask 应用。这是一个能够对访问者进行计数并将其保存到 Redis 的简单的 Web 服务。

version: "3.5"
services:
web-fe:
build: .
command: python app.py
ports:
- target: 5000
published: 5000
networks:
- counter-net
volumes:
- type: volume
source: counter-vol
target: /code
redis:
image: "redis:alpine"
networks:
counter-net:

networks:
counter-net:

volumes:
counter-vol:

在深入研究之前粗略观察文件的基本结构,首先可以注意到,它包含 4 个一级 key:version、services、networks、volumes。

version 是必须指定的,而且总是位于文件的第一行。它定义了 Compose 文件格式(主要是 API)的版本。

    注意,version 并非定义 Docker Compose 或 Docker 引擎的版本号。

示例中 Compose 文件将使用版本 3 及以上的版本。

services 用于定义不同的应用服务。上边的例子定义了两个服务:一个名为 web-fe 的 Web 前端服务以及一个名为 redis 的内存数据库服务。Docker Compose 会将每个服务部署在各自的容器中。

networks 用于指引 Docker 创建新的网络。默认情况下,Docker Compose 会创建 bridge 网络。这是一种单主机网络,只能够实现同一主机上容器的连接。当然,也可以使用 driver 属性来指定不同的网络类型。

下面的代码可以用来创建一个名为 over-net 的 Overlay 网络,允许独立的容器(standalone container)连接(attachable)到该网络上。

networks:
over-net:
driver: overlay
attachable: true

volumes 用于指引 Docker 来创建新的卷。

上面例子中的 Compose 文件使用的是 v3.5 版本的格式,定义了两个服务,一个名为 counter-net 的网络和一个名为 counter-vol 的卷。

更多的信息在 services 中,下面仔细分析一下。

Compose 文件中的 services 部分定义了两个二级 key:web-fe 和 redis。

它们各自定义了一个应用程序服务。需要明确的是,Docker Compose 会将每个服务部署为一个容器,并且会使用 key 作为容器名字的一部分。

本例中定义了两个 key:web-fe 和 redis。因此 Docker Compose 会部署两个容器,一个容器的名字中会包含 web-fe,而另一个会包含 redis。

web-fe 的服务定义中,包含如下指令。
1) build
指定 Docker 基于当前目录(.)下 Dockerfile 中定义的指令来构建一个新镜像。该镜像会被用于启动该服务的容器。
2) command
python app.py 指定 Docker 在容器中执行名为 app.py 的 Python 脚本作为主程序。因此镜像中必须包含 app.py 文件以及 Python,这一点在 Dockerfile 中可以得到满足。
3) ports
指定 Docker 将容器内(-target)的 5000 端口映射到主机(published)的 5000 端口。这意味着发送到 Docker 主机 5000 端口的流量会被转发到容器的 5000 端口。容器中的应用监听端口 5000。
4) networks
使得 Docker 可以将服务连接到指定的网络上。这个网络应该是已经存在的,或者是在 networks 一级 key 中定义的网络。对于 Overlay 网络来说,它还需要定义一个 attachable 标志,这样独立的容器才可以连接上它(这时 Docker Compose 会部署独立的容器而不是 Docker 服务)。
5) volumes
指定 Docker 将 counter-vol 卷(source:)挂载到容器内的 /code(target:)。counter-vol 卷应该是已存在的,或者是在文件下方的 volumes 一级 key 中定义的。

综上,Docker Compose 会调用 Docker 来为 web-fe 服务部署一个独立的容器。该容器基于与 Compose 文件位于同一目录下的 Dockerfile 构建的镜像。

基于该镜像启动的容器会运行 app.py 作为其主程序,将 5000 端口暴露给宿主机,连接到 counter-net 网络上,并挂载一个卷到/code。

从技术上讲,本例并不需要配置 command: python app.py。因为镜像的 Dockerfile 已经将 python app.py 定义为了默认的启动程序。但是,本例主要是为了展示其如何执行,因此也可用于覆盖 Dockerfile 中配置的 CMD 指令。

redis 服务的定义相对比较简单。
6) image
redis:alpine 使得 Docker 可以基于 redis:alpine 镜像启动一个独立的名为 redis 的容器。这个镜像会被从 Docker Hub 上拉取下来。
7) networks
配置 redis 容器连接到 counter-net 网络。

由于两个服务都连接到 counter-net 网络,因此它们可以通过名称解析到对方的地址。了解这一点很重要,本例中上层应用被配置为通过名称与 Redis 服务通信。

根据docker-compose文件部署应用

下面将实际部署 Compose 文件中定义的应用。可以从我的百度网盘(https://pan.baidu.com/s/1Q0tcQnSqUQ06rfEdH_MBaw 提取码: a55v)下载所需的文件。

将代码下载到本地,并部署到新创建的名为 counter-app 的目录中。

该目录包含所需的所有文件,可以作为构建上下文。

本文把下载的文件放在了主目录下。

Docker Compose 会使用目录名(counter-app)作为项目名称,这一点在后续的操作中会看到,Docker Compose 会将所有的资源名称中加上前缀 counter-app_。

进入 counter-app 目录中,检查文件是否存在。

简要介绍这几个文件。

    app.py:是应用程序代码(一个 Python Flask 应用)。
    docker-compose.yml:是 Compose 文件,其中定义了 Docker 如何部署应用。
    Dockerfile:定义了如何构建 web-fe 服务所使用的镜像。
    requirements.txt:列出了应用所依赖的 Python 包。

app.py 显然是应用的核心文件,而 docker-compose.yml 文件将应用的所有组件组织起来。

下面使用 Docker Compose 将应用启动起来。以下所有的命令都是运行在刚才创建的 counter-app 目录下的。

$ docker-compose up &

常用的启动一个 Compose 应用(通过 Compose 文件定义的多容器应用称为“Compose 应用”)的方式就是 docker-compose up 命令。它会构建所需的镜像,创建网络和卷,并启动容器。默认情况下,docker-compose up 会查找名为 docker-compose.yml 或 docker-compose.yaml 的 Compose 文件。如果 Compose 文件是其他文件名,则需要通过 -f 参数来指定。

如下命令会基于名为 prod-equus-bass.yml 的 Compose 文件部署应用。

$ docker-compose -f prod-equus-bass.yml up

使用 -d 参数在后台启动应用也是常见的用法

docker-compose up -d

或者是

docker-compose -f prod-equus-bass.yml up -d

前面的示例命令在前台启动应用(没有使用 -d 参数),但是使用了 & 将终端窗口返回。

这样应用就构建并启动起来了,可以直接使用 docker 命令来查看 Docker Compose 创建的镜像、容器、网络和卷。

$ docker image ls

可以看到有 3 个在部署过程中构建或拉取的镜像。

counterapp_web-fe:latest 镜像源自 docker-compose.yml 文件中的 build: . 指令。该指令让 Docker 基于当前目录下的 Dockerfile 来构建一个新的镜像。该镜像基于 python:3.4-alpine 构建,其中包含 Python Flask Web 应用的程序代码。更多信息可以通过查看 Dockerfile 的内容进行了解。

    FROM python:3.4-alpine << 基础镜像
    ADD . /code << 将app复制到镜像中
    WORKDIR /code << 设置工作目录
    RUN pip install -r requirements.txt << 安装依赖
    CMD ["python", "app.py"] << 设置默认启动命令

为了方便理解,每一行都添加了注释。部署时要删除掉。

请注意,Docker Compose 会将项目名称(counter-app)和 Compose 文件中定义的资源名称(web-fe)连起来,作为新构建的镜像的名称。

Docker Compose 部署的所有资源的名称都会遵循这一规范。

由于 Compose 文件的 .Services.redis 项中指定了 image: "redis:alpine",因此会从 Docker Hub 拉取 redis:alpine 镜像。

如下命令列出了两个容器。每个容器的名称都以项目名称(所在目录名称)为前缀。此外,它们还都以一个数字为后缀用于标识容器实例序号,因为 Docker Compose 允许扩缩容。 

counterapp_web-fe 容器中运行的是应用的 Web 前端。其中执行的是 app.py,并且被映射到了 Docker 主机的 5000 端口,稍后会进行连接。

如下的网络和卷列表显示了名为 counterapp_counter-net 的网络和名为 counterapp_counter-vol 的卷。

应用部署成功后,可以用 Docker 主机的浏览器连接 5000 端口来查看应用的运行效果,如下图所示。

单击浏览器的刷新按钮,计数会增加。

如果使用 & 启动应用,那么可以在终端窗口中看到包含 HTTP 响应码 200 的日志。这表明请求收到了正确的响应,每次加载页面都会有日志打印出来。

到此,多容器的应用已经借助 Docker Compose 成功部署了。

使用docker-compose子命令管理应用

下面再来介绍一下如何使用 Docker Compose 启动、停止和删除应用,以及获取应用状态。并且还会演示如何使用挂载的卷来实现对 Web 前端的更新。

既然应用已经启动,下面看一下如何使其停止。为了实现这一点,将子命令 up 替换成 down 即可。

由于是使用 & 启动的应用,因此它运行在前台。这意味着在终端上会打印详细的输出,从而可以很好地了解其执行过程。下面介绍一下每一行都代表什么意思。

第 1、2 行开始尝试关闭两个服务,即 Compose 文件中定义的 web-fe 和 redis。由第 3 行可知 stop 指令会发送 SIGTERM 信号。信号会被发送到每个容器中 PID 为 1 的进程。第 4~6 行显示 Redis 容器接收到信号后优雅地自行关闭。第 7、8 行表明已成功停止 Redis。第 9 行表明 web-fe 服务也被成功停止。由第 10 和 11 行可知已停止的服务被删除。第 12 行显示 counter-net 网络被删除,第 13 行显示 docker-compose up 进程退出。

需要特别注意的是,counter-vol 卷并没有被删除,因为卷应该是用于数据的长期持久化存储的。因此,卷的生命周期是与相应的容器完全解耦的。执行 docker volume ls 可见该卷依然存在于系统中。写到卷上的所有数据都会保存下来。

同样,执行 docker-compose up 过程中拉取或构建的镜像也会保留在系统中。因此,再次部署该应用将更加快捷。

下面继续介绍其他几个 docker-compose 子命令。使用如下命令再次启动应用,但是这次在后台启动它。

$ docker-compose up -d

这时会发现这次启动要快很多——因为 counter-vol 卷已经存在,而且不需要去拉取和构建镜像。

使用 docker-compose ps 命令来查看应用的状态。 

输出中会显示容器名称、其中运行的 Command、当前状态以及其监听的网络端口。

使用 docker-compose top 命令列出各个服务(容器)内运行的进程。

其中 PID 编号是在 Docker 主机上(而不是容器内)的进程 ID。

docker-compose stop 命令会停止应用,但并不会删除资源。然后再次运行 docker-compose ps 查看状态。

可以看到,停止 Compose 应用并不会在系统中删除对应用的定义,而仅将应用的容器停止。这一点可以使用 docker container ls -a 命令进行验证。

对于已停止的 Compose 应用,可以使用 docker-compose rm 命令来删除。这会删除应用相关的容器和网络,但是不会删除卷和镜像。

当然,也不会删除应用源码(项目目录下的 app.py、Dockerfile、requirements.txt 和 docker-compose.yml)。

执行 docker-compose restart 命令重启应用。

使用 docker-compose down 这一个命令就可以停止和关闭应用。

应用被删除,仅留下了镜像、卷和源码。下面最后一次部署应用,然后查看卷的情况。

查看 Compose 文件会发现,其中定义了一个名为 counter-vol 的新卷,并将其挂载到 web-fe 服务的 /code 路径上。

当第一次部署该应用的时候,Docker Compose 会检查是否有同名的卷存在。如果不存在,则会创建它。也可使用 docker volume ls 命令手动查看。

Docker Compose 会在部署服务之前创建网络和卷。这很合理,因为它们是供服务(容器)使用的底层基础资源。Docker Compose 会首先创建网络和卷(甚至先于构建和拉取镜像)。查看执行的命令docker-compose up -d之后的图上显示的:

Creating network "counter-app_counter-net" with the default driver

再次研读 Dockerfile 中关于 web-fe 服务的定义,会看到它将卷 counter-app 挂载到容器的 /code 目录。还会发现,/code 正是应用安装和执行的目录。由此可知,应用的代码是位于 Docker 卷中的,如下图所示。

在 Docker 主机对卷中文件的修改,会立刻反应到应用中。下面验证一下。

具体的验证过程包含这样几个步骤。首先在项目目录下编辑 app.py 文件,从而应用在浏览器中的页面会显示不同的文本。然后将更新的文件复制到位于 Docker 主机的卷中。最后刷新应用的 Web 页面来查看更新的内容。

所有对位于 Docker 主机上的卷中内容的修改都会立刻反映在容器内的卷里。

使用顺手的文本编辑器修改位于项目目录下的 app.py 文件,这里使用的是 vim。

$ vim ~/counter-app/app.py

修改第 22 行位于双引号之间的文字。这一行以 "What's up..." 开始,可在双引号内随意输入文字并保存。如果没有安装vim要使用sudo apt install vim 命令来安装,之后进入vim编辑器,按下i进入插入修改模式,找到位置修改后,按下esc键,输入:wq回车即可保存退出。

更新源码后,将其复制到 Docker 主机上相应的卷中,也就是复制到一个或多个容器的挂载点(Mount Point)中。

使用 docker volume inspect 命令可以查看卷位于 Docker 主机的什么位置。

$ docker volume inspect counterapp_counter-vol | grep Mount

复制文件后,该文件就会出现在 web-fe 容器的 /code 中,覆盖掉容器中原有的 /code/app.py 文件。

$ cp ~/counterapp/app.py \
/var/lib/docker/volumes/counterapp_counter-vol/_data/app.py

现在更新的 app.py 文件已经位于容器中了。在浏览器中通过 Docker 主机的 IP 和端口 5000 连接到应用来查看更新的内容。

常用命令

 1) docker-compose up
用于部署一个 Compose 应用。默认情况下该命令会读取名为 docker-compose.yml 或 docker-compose.yaml 的文件。当然用户也可以使用 -f 指定其他文件名。通常情况下,会使用 -d 参数令应用在后台启动。
2) docker-compose stop
停止 Compose 应用相关的所有容器,但不会删除它们。被停止的应用可以很容易地通过 docker-compose restart 命令重新启动。
3) docker-compose rm
用于删除已停止的 Compose 应用。它会删除容器和网络,但是不会删除卷和镜像。
4) docker-compose restart
重启已停止的 Compose 应用。如果用户在停止该应用后对其进行了变更,那么变更的内容不会反映在重启后的应用中,这时需要重新部署应用使变更生效。
5) docker-compose ps
用于列出 Compose 应用中的各个容器。输出内容包括当前状态、容器运行的命令以及网络端口。
6) docker-compose down
停止并删除运行中的 Compose 应用。它会删除容器和网络,但是不会删除卷和镜像。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值