参考文档: Docker Compose 是什么
Docker Compose 是什么
Docker Compose
与 Docker stack
非常类似。它能够在 Docker 节点上,以单引擎模式进行多容器应用的部署和维护。
多数的现代应用通过多个更小的服务互相协同来组成一个完整可用的应用。比如一个简单的示例应用可能由下面4个服务组成。
- web 前端;
- 订单管理;
- 品类管理;
- 后台数据库。
将以上服务组织在一起,就是一个可用的应用。
部署和管理繁多的服务是困难的。而这正是 Docker Compose
要解决的问题。
Docker Compose
并不是通过脚本和各种冗长的 docker
命令来将应用组件组织起来,而是通过一个声明式的配置文件描述整个应用,从而使用一条命令完成部署。
应用部署成功后,还可以通过一系列简单的命令实现对其完整声明周期的管理。甚至,配置文件还可以置于版本控制系统中进行存储和管理。
Docker Compose 的背景
Docker Compose 的前身是 Fig
。Fig
是一个基于 Docker 的 Python 工具,允许用户基于一个 YAML 文件定义多容器应用,从而可以使用 fig
命令行工具进行应用的部署。fig
还可以对应用的全生命周期进行管理。
内部实现上,Fig 会解析 YAML 文件,并通过 Docker API 进行应用的部署和管理。
Docker Compose 的安装
Docker Compose 可用于多种平台。此处基于 Linux 平台进行介绍。在 Linux 上安装 Docker Compose 可以使用系统软件包管理工具(yum),或者 Python 包管理工具(pip) 进行安装,也可以直接下载 docker-compose
二进制文件,然后添加执行权限,并在系统环境变量中进行声明即可。
使用 系统软件包管理用户已安装
1
yum install -y docker-compose
使用 Python 包管理工具安装
1
pip install docker-compose
使用下载二进制文件的方式安装
1
2
3
4
5
6
7# 1. 前往 https://github.com/docker/compose/releases 地址下载压缩包
# 2. 解压文件到 PATH 环境变量包含的路径下,此处以 /usr/local/bin 为例
# 3. 给二进制文件添加执行权限
chmod +x /usr/local/bin/docker-compose
# 4. 检查安装情况以及版本
docker-compose --version
docker-compose version 1.18.0, build 8dd22a9
Docker Compose 应用配置文件
Docker Compose 使用 YAML 文件来定义多服务的应用。YAML 是 JSON 的一个子集,因此也可以使用 JSON。
Docker Compose默认使用全文件名 docker-compose.yml
。当然,也可以使用 -f
参数指定具体的文件。
如下是一个简单的 Compose 文件的示例,它定义了一个包含两个服务(web-fe 和 redis)的小型 Flask 应用。这是一个能够对访问者进行计数并将其保存到 Redis 的简单的 web 服务。
1 | version: "3.5" |
在深入研究之前粗略观察文件基本结构,首先可以观察到,它包含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 网络,允许独立的容器连接到该网络上。1
2
3
4networks:
over-net:
driver: overlay
attachable: truevolumes
用于指引 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 的服务定义中,包含如下指令
build
指定 Docker 基于当前目录 (.
) 下的 Dockerfile 中定义的指令来构建一个新镜像。该镜像会被用于启动该服务的容器
command
python app.py
指定 Docker 在容器中执行名为 app.py
的 Python 脚本作为主程序。因此镜像中必须包含 app.py
文件以及 Python,这一点在 Dockerfile 中可以得到满足。
ports
指定 Docker 容器内 (- target
) 的 5000 端口映射到主机 (published
) 的 5000 端口。这意味着发送到 Docker 主机 5000 端口的流量会被转发到容器的 5000 端口。容器中的应用监听端口 5000.
networks
使得 Docker 可以将服务连接到指定的网络上。这个网络应该是已经存在的,或者是在 networks
一级 key 中定义的网络。
对于 Overlay 网络来说,它还需要定义一个 attachable
标志,这样独立的容器才可以连接上它(这时 Docker Compose 会部署独立的容器而不是 Docker 服务).
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 服务的定义相对简单
image
redis:alpine
使 Docker 可以基于 redis:alpine
镜像启动一个独立的名为 redis
的容器。这个镜像会被从 Docker Hub 上拉取下来。
networks
配置 redis
容器连接到 counter-net
网络。由于两个服务都连接到 counter-net
网络,因此它们可以通过名称解析到对方的地址。
Docker Compose 部署应用
下面将实际部署 Compose 文件中定义的应用。
将代码下载到本地
1
git clone https://gitee.com/lonely0422/counter-app.git
进入
counter-app
目录中,检查文件是否存在1
2ls
app.py docker-compose.yml Dockerfile README.md requirements.txt简单介绍这几个文件:
app.py
: 是应用程序代码(一个 flask 应用)docker-compose.yml
: 是 Compose 文件,其中定义了 Docker 如何部署应用Dockerfile
: 定义了如何构建 web-fe 服务所使用的镜像requirements.txt
: 列出了应用所依赖的 Python 包
下面使用 Docker Compose 将应用启动起来。
1
2
3
4
5
6
7
8
9
10
11
12
13docker-compose up &
Creating network "counter-app_counter-net" with the default driver
Creating volume "counter-app_counter-vol" with default driver
...
web-fe_1 | * Serving Flask app "app" (lazy loading)
web-fe_1 | * Environment: production
web-fe_1 | WARNING: This is a development server. Do not use it in a production deployment.
web-fe_1 | Use a production WSGI server instead.
web-fe_1 | * Debug mode: on
web-fe_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web-fe_1 | * Restarting with stat
web-fe_1 | * Debugger is active!
web-fe_1 | * Debugger PIN: 336-223-227
启动应用将花费一点时间,其输出也非常详尽。下面我们讲解一下 docker-compose
命令。
常用的启动一个 Compose 应用(通过 Compose 文件定义的多容器应用称为 Compose 应用)的方式就是 docker-compose up
命令。它会构建所需的镜像,创建网络和卷,并且动容器。
默认情况下,docker-compose up
会查找名为 docker-compose.yml
或者 docker-compose.yaml
的 Compose 文件。如果 Compose 文件是其他文件名,则需要通过 -f
参数来指定。如下命令会基于名为 prod-equus-bass.yml
的 Compose 文件部署应用。
1 | docker-compose -f prod-equus-bass.yml up |
使用 -d
参数在后台启动应用也是常见的用法,代码如下:
1 | docker-compose up -d |
前面的示例命令在前台启动应用(没有使用 -d
参数),但是使用了 &
将终端窗口返回。这种用法不太正规,所有的日志还是会直接输出到我们后续可能会用的终端窗口上。
docker-compose 常用命令
上面已经将应用成功的部署好了,下面介绍一下如何使用 Docker Compose 启动停止和删除应用,以及获取应用的状态。并且还会演示如何使用挂载的卷来实现对 web 前端的更新
启动应用 up
启动应用详细的用法参考上一节所讲内容
查看应用状态 ps
查看应用的状态可以使用 docker-compose ps
子命令,输出中会显示容器名称,其中运行的 Command
,当前状态以及监听的网络端口。
1 | # docker-compose -f Docker_compose/counter-app/docker-compose.yml ps |
查看应用各个服务(容器)运行的进程 top
使用 docker-compose top
命令列出各个服务(容器)内运行的进程
1 | docker-compose top |
其中 PID 编号是在 Docker 主机上(而不是容器内)的进程 ID。
停止应用 stop
使用 docker-compose stop
命令会停止应用,但并不会删除资源,然后再次运行 docker-compose ps
查看状态:
1 | # docker-compose stop |
可以看到,停止 Compose 应用并不会在系统中删除对应用的定义,而是仅将应用的容器停止。这一点可以使用 docker container ls -a
命令进行验证。
删除应用 rm
对于已停止的 Compose 应用可以使用 docker-compose rm
命令来删除。这会删除应用相关的容器和网络,但是不会删除卷和镜像。当然,也不会删除应用源码。
1 | # docker-compose rm |
重启应用 restart
使用 docker-compose restart
命令可以重启应用
1 | # docker-compose restart |
停止并关闭应用 down
使用 docker-compose down
命令可以停止和关闭应用。使用这个命令,应用会被删除,仅留下镜像,卷和源码。
1 | # docker-compose down |
更新应用内容
再次研读 Dockerfile 中关于 web-fe 服务的定义,会看到它将卷 counter-vol
挂载到容器的的 /code
目录。还会发现,/code
正是应用安装和执行的目录。由此可见,应用的代码时位于 Docker 卷中的,这意味着,我们在 Docker 主机对卷中文件的修改,会立刻反应到应用中。下面验证一下。
具体的验证过程包含这样几个步骤:
- 首先在项目目录下编辑 app.py 文件,从而应用在浏览器中的页面会显示不同的文本;
- 然后将更新的文件复制到位于 Docker 主机的卷中;
- 最后刷新应用的web 页面来查看更新的内容,因为,所有对位于 Docker 主机上的卷中内容的修改都会立刻反应在容器内的卷里。
编辑 counter-app/app.py 文件
编辑 app.py
文件,修改文件内 hell()
方法的返回值,如下:
1 | def hello(): |
复制 app.py 文件到卷中
使用 docker volume inspect
命令可以查看卷位于 Docker 主机的什么位置
1 | # docker volume inspect counter-app_counter-vol |grep Mount |
将 app.py
文件复制到 /var/lib/docker/volumes/counter-app_counter-vol/_data
目录下
查看更新
使用浏览器访问 http://192.168.47.100:5000
,这个地址,可以查看到前端已更新内容。或者使用 curl
命令也可以验证。
1 | $ curl http://127.0.0.1:5000/ |