前言
我们使用 Docker 的时候,定义 Dockerfile 文件,然后使用 docker build、docker run 等命令操作容器。然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知。
Dockerfile可以让用户管理一个单独的应用容器;而Compose则允许用户在一个模板(YAML格式)中定义一组相关联的应用容器(被称为一个 project,即项目)
例如一个 Web 服务容器再加上后端的数据库服务容器等。
这样挨个启动容器,是不是很烦人,能不能写个脚本,按照依赖顺序依次启动相应容器呢?
---- Docker compose它来了
Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。
然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器,Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。
目录
如何使用Docker Compose部署多容器的应用。
Docker Compose与Docker Stack非常类似。
本部分主要介绍Docker Compose,它能够在Docker节点上,以单引擎模式(Single-Engine Mode)进行多容器应用服务的部署和管理。
后续将介绍Docker Stack,它能够以Swarm模式对Docker节点上的多容器应用服务进行部署和管理。(Docker Swarm可以将一个应用服务部署到多个主机,Docker Stack 🟰 Docker Compose + Docker Swarm)
一、 使用Docker Compose部署应用——简介
多数的现代应用通过多个更小的服务互相协同来组成一个完整可用的应用。
比如一个简单的示例应用可能由如下4个服务组成:Web前端。订单管理。品类管理。后台数据库。将以上服务组织在一起,就是一个可用的应用。
部署和管理繁多的服务是困难的。而这正是Docker Compose要解决的问题。
Docker Compose并不是通过脚本和各种冗长的docker 命令来将应用组件组织起来,而是通过一个声明式的配置文件描述整个应用,从而使用一条命令完成部署。
这个工具可以通过一个yml文件定义多容器的docker应用
通过一条命令就可以根据yml文件的定义去创建或管理这多个容器
应用部署成功后,还可以通过一系列简单的命令实现对其完整声明周期的管理。甚至,配置文件还可以置于版本控制系统中进行存储和管理。这是显著的进步!
二、 使用Docker Compose部署应用——详解
Docker Compose的背景
安装Docker Compose
Compose文件
使用Docker Compose部署应用
使用Docker Compose管理应用
1 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 核心概念
Docker Compose将所管理的容器分为三层, 分别是工程项目(project),服务(service)以及容器(containner)
docker-compose运行目录下的所有文件(docker-compose.yml文件、extends文件或环境变量等)组成一个工程项目,如无特殊指定,工程项目名即为当前目录名。
一个工程项目当中,可以包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖。
一个服务中可以包括多个容器实例,docker-compose并没有解决负载均衡的问题。因此需要借助其他工具实现服务发现及负载均衡,比如consul。
docker-compose的工程配置文件默认为 docker-compose.yml。可以通过环境变量COMPOSE_FILE -f 参数自定义配置文件,其自定义多个有依赖关系的服务及每个人服务运行的容器。
2 安装Docker Compose
Compose 和 Docker 兼容性
Compose 文件格式有多个版本:1、2、2.x、和 3.x。下面的表格是 Compose 文件所支持的指定的 docker 发行版:
Docker Compose可用于多种平台。我们将介绍在Windows、Mac以及Linux上的几种安装方法
1.在Windows 10上安装Docker Compose
在Windows 10上运行Docker的推荐工具是Windows版Docker(Docker for Windows, DfW)。Docker Compose会包含在标准DfW安装包中。所以,安装DfW之后就已经有Docker Compose工具了。
在PowerShell或CMD终端中使用如下命令可以检查Docker Compose是否安装成功。
【Docker】深入浅出Docker基础——Docker安装
2.在Mac上安装Docker Compose
与Windows 10一样,Docker Compose也作为Mac版Docker(Docker for Mac, DfM)的一部分进行安装,所以一旦安装了DfM,也就安装了Docker Compose。
在终端中运行如下命令检查Docker Compose是否安装。
【Docker】深入浅出Docker基础——Docker安装
3.在Windows Server上安装Docker Compose
Docker Compose在Windows Server上是作为一个单独的二进制文件安装的。因此,使用它的前提是确保在Windows Server上已经正确安装了Docker。
在PowerShell终端中输入如下命令来安装Docker Compose。为了便于阅读,下面的命令使用反引号(`)来对换行进行转义,从而将多行命令合并。
下面的命令安装的是1.18.0 版本的Docker Compose,读者请自行选择版本号:https://github. com/docker/compose/releases。只需要将URL中的1.18.0替换为你希望安装的版本即可。
使用docker-compose --version 命令查看安装情况。
Docker Compose安装好了,只要Windows Server上安装有Docker引擎即可使用。
4.在Linux上安装Docker Compose
在Linux上安装Docker Compose分为两步。
首先使用curl 命令下载二进制文件
然后使用chmod 命令将其置为可运行。
Docker Compose在Linux上的使用,同样需要先安装有Docker引擎。
如下命令会下载1.18.0 版本的Docker Compose到/usr/bin/local 。请在GitHub上查找想安装的版本,并替换URL中的1.18.0 。
下面的示例是一条写成多行的命令,如果要将其合并为一行,请删掉反斜杠(\ )。
下载docker-compose二进制文件后,使用如下命令使其可执行。
$ chmod +x /usr/local/bin/docker-compose
检查安装情况以及版本。
$ docker-compose --version
docker-compose version 1.18.0, build 8dd22a9
现在就可以在Linux上使用Docker Compose了。
此外,也可以使用pip 来安装Docker Compose的Python包。
3 Compose文件(Docker compose file)
Docker Compose使用YAML文件来定义多服务的应用。
YAML是JSON的一个子集,因此也可以使用JSON。
不过我们的例子将全部采用YAML。
Docker Compose默认使用文件名docker-compose.yml (docker compose file,也就是这个配置文件)。当然,用户也可以使用-f 参数指定具体文件。
如下是一个简单的Compose文件的示例,它定义了一个包含两个服务(webfe 和redis )的小型Flask应用。这是一个能够对访问者进行计数并将其保存到Redis的简单的Web服务。我们将其命名为counter-app ,并将其作为后续的示例应用程序。
编排中的字段详解
在深入研究之前粗略观察Docker Compose 编排文件的基本结构,首先可以注意到,它包含4个一级key:version 、services 、networks 、volumes 。这些重要的字段需要了解:
version
docker compose file配置文件,是有version的
version 是必须指定的,而且总是位于文件的第一行。它定义了Compose文件格式(主要是API)的版本。
建议使用最新版本。推荐使用version=3的,因为version=2的,只能在单机环境下使用。虽然version=3默认也是在单机环境下使用的,但是version=3是可以在多个机器的环境下使用的
注意,version 并非定义Docker Compose或Docker引擎的版本号。
services
services 用于定义不同的应用服务。上边的例子定义了两个服务:
一个名为web-fe 的Web前端服务
一个名为redis 的内存数据库服务
Docker Compose会将每个服务部署在各自的容器中。
一个service代表一个container,这个container可以从dockerhub的image来创建,或者从本地的Dockerfile build出来的image来创建
service的启动类似docker run,我们可以给其指定network和volume,所以可以给service指定network和volume的引用
networks
networks 用于指引Docker创建新的网络。默认情况下,Docker Compose会创建bridge 网络。这是一种单主机网络,只能够实现同一主机上容器的连接。当然,也可以使用driver 属性来指定不同的网络类型。
下面的代码可以用来创建一个名为over-net 的Overlay网络,允许独立的容器(standalone container)连接(attachable )到该网络上。
volumes
volumes 用于指引Docker来创建新的卷。
分析示例中的Compose文件
上面例子中的 Compose 文件使用的是 v3.5 版本的格式,定义了两个服务,一个名为counter-net 的网络和一个名为counter-vol 的卷。
更多的信息在services 中,下面仔细分析一下
services
Compose文件中的services 部分定义了两个二级key:web-fe 和redis 。它们各自定义了一个应用程序服务。
需要明确的是,Docker Compose会将每个服务部署为一个容器,并且会使用key作为容器名字的一部分。
本例中定义了两个key:web-fe 和redis 。因此Docker Compose会部署两个容器,一个容器的名字中会包含web-fe ,而另一个会包含redis 。
(1)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 。
(2)redis 服务的定义相对比较简单
image: redis:alpine 使得Docker可以基于redis:alpine 镜像启动一个独立的名为redis 的容器。这个镜像会被从Docker Hub上拉取下来。
networks :配置redis 容器连接到counter-net 网络。由于两个服务都连接到counter-net 网络,因此它们可以通过名称解析到对方的地址。了解这一点很重要,本例中上层应用被配置为通过名称与Redis服务通信。
补充:Compose配置常用字段
4 使用Docker Compose部署应用
我们将实际部署上面介绍的 Compose file 文件中定义的应用。你可以从我的GitHub主页中的counter-app下载所需的文件。
将Git库克隆到本地。使克隆下来的代码文件位于一个新创建的名为counterapp 的目录中。该目录包含所需的所有文件,可以作为构建上下文。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 命令。
常用的启动一个Compose应用(通过Compose文件定义的多容器应用称为“Compose应用”)的方式就是docker-compose up 命令。它会构建所需的镜像,创建网络和卷,并启动容器。
默认情况下,docker-compose up 会查找名为docker-compose.yml 或docker-compose.yaml 的Compose文件。如果Compose文件是其他文件名,则需要通过-f 参数来指定。
如下命令会基于名为prod-equus-bass.yml 的Compose文件部署应用。
使用-d 参数在后台启动应用也是常见的用法,代码如下。
前面的示例命令在前台启动应用(没有使用-d 参数),但是使用了& 将终端窗口返回。这种用法不太正规,所有的日志还是会直接输出到我们后续可能会用的终端窗口上。
这样应用就构建并启动起来了,你可以直接使用docker 命令来查看Docker Compose创建的镜像、容器、网络和卷。
可以看到有3个在部署过程中构建或拉取的镜像。
counterapp_web-fe:latest 镜像源自docker-compose.yml 文件中的build: . 指令。该指令让Docker基于当前目录下的Dockerfile来构建一个新的镜像。该镜像基于python:3.4-alpine 构建,其中包含Python Flask Web应用的程序代码。更多信息可以通过查看Dockerfile 的内容进行了解。
为了方便理解,每一行都添加了注释。部署时要删除掉。
请注意,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 端口来查看应用的运行效果,如图9.1所示。
单击浏览器的刷新按钮,计数会增加。感兴趣的读者可以查看app.py 是如何在Redis中存储计数的。
如果使用& 启动应用,那么可以在终端窗口中看到包含HTTP响应码200的日志。这表明请求收到了正确的响应,每次加载页面都会有日志打印出来。
恭喜!到此为止,多容器的应用已经借助Docker Compose成功部署了。
5 使用Docker Compose管理应用
介绍如何使用Docker Compose启动、停止和删除应用,以及获取应用状态。还会演示如何使用挂载的卷来实现对Web前端的更新。
既然应用已经启动,下面看一下如何使其停止。为了实现这一点,将子命令up替换成down 即可。
$ docker-compose 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会首先创建网络和卷(甚至先于构建和拉取镜像)。
再次研读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... "开始,读者可在双引号内随意输入文字并保存。
更新源码后,将其复制到Docker主机上相应的卷中,也就是复制到一个或多个容器的挂载点(Mount Point)中。使用docker volume inspect 命令可以查看卷位于Docker主机的什么位置。
复制文件后,该文件就会出现在web-fe 容器的/code 中,覆盖掉容器中原有的/code/app.py 文件。
现在更新的app.py文件已经位于容器中了。请在浏览器中通过Docker主机的IP和端口5000连接到应用来查看更新的内容。
更新后的情况如图所示。
显然在生产环境中不会这样做,但是在开发环境中这确实很节省时间。
到此为止,本部分通过一个简单的多容器应用的例子,介绍了如何使用Docker Compose进行部署和管理!Docker Compose可以用来部署和管理复杂得多的应用。
Docker Compose 常用命令
三、 使用Docker Compose部署应用——命令
docker-compose up 命令用于部署一个Compose应用。默认情况下该命令会读取名为docker-compose.yml 或docker-compose.yaml 的文件,当然用户也可以使用-f 指定其他文件名。通常情况下,会使用-d参数令应用在后台启动。
docker-compose stop 命令会停止Compose应用相关的所有容器,但不会删除它们。被停止的应用可以很容易地通过docker-compose restart命令重新启动。
docker-compose rm 命令用于删除已停止的Compose应用。它会删除容器和网络,但是不会删除卷和镜像。
docker-compose restart 命令会重启已停止的Compose应用。如果用户在停止该应用后对其进行了变更,那么变更的内容不会反映在重启后的应用中,这时需要重新部署应用使变更生效。
docker-compose ps 命令用于列出Compose应用中的各个容器。输出内容包括当前状态、容器运行的命令以及网络端口。
docker-compose down 会停止并删除运行中的Compose应用。它会删除容器和网络,但是不会删除卷和镜像。
小结
介绍了如何使用Docker Compose部署和管理一个多容器的应用。
Docker Compose是一个基于Docker Engine进行安装的Python工具。该工具使得用户可以在一个声明式的配置文件中定义一个多容器的应用,并通过一个简单的命令完成部署。
Compose文件可以是YAML或JSON格式,其中定义了所有的容器、网络、卷以及应用所需的密码。docker-compose 命令行工具会解析该文件,并调用Docker来执行部署。
一旦应用完成部署,用户就可以使用不同的docker-compose 子命令来管理应用的整个生命周期。
还介绍了如何使用挂载卷来修改容器内的文件。
Docker Compose在开发者中得到广泛使用,而且对应用来说,Compose文件也是一种非常不错的文档——其中定义了组成应用的所有服务,它们使用的镜像、网络和卷,暴露的端口,以及更多信息。基于此,我们可以弥合开发与运维之间的隔阂。Compose文件应该被当作代码,因此应该将其保存在源控制库中。
——The End——
记得点赞、分享,让更多的朋友一起探索这个IT世界的新篇章!
AIGC周边正在发布,关注生活,冻龄青春
推荐阅读
【Docker】深入浅出Docker基础——走进Docker
【Docker】深入浅出Docker基础——Docker安装
【Docker】深入浅出Docker基础进阶——纵观Docker的运维与开发
【Docker】深入浅出Docker技术——Docker引擎(理论)
【Docker】深入浅出Docker技术——Docker镜像
【Docker】深入浅出Docker技术——Docker容器
【Docker】深入浅出Docker技术——应用的容器化(单节点Dockerfile)
【Docker】秒懂 Dockerfile:构建容器镜像的必备利器
【Docker】从零开始:教你将程序打包成 Docker 镜像
【云部署】Win11+WSL2+Ubuntu+Docker-Desktop 支持GPU的深度学习环境搭建
领取专属 10元无门槛券
私享最新 技术干货