简介
Docker 是一个用于在软件容器内部自动部署 Linux 应用程序的强大工具,但要充分发挥其潜力,最好是让应用程序的每个组件都在自己的容器中运行。对于具有许多组件的复杂应用程序,编排所有容器一起启动和关闭(更不用说彼此通信)很快就会变得难以控制。
Docker 社区提出了一个流行的解决方案,称为 Fig,它允许您使用单个 YAML 文件来编排所有 Docker 容器和配置。这变得非常受欢迎,以至于 Docker 团队决定基于 Fig 源码制作 Docker Compose,而 Fig 现在已经被弃用。Docker Compose 使用户更容易地编排 Docker 容器的进程,包括启动、关闭和设置容器之间的链接和卷。
在本教程中,您将安装最新版本的 Docker Compose,以帮助您管理多容器应用程序,并将探索该软件的基本命令。
Docker 和 Docker Compose 概念
使用 Docker Compose 需要将一堆不同的 Docker 概念结合在一起,因此在开始之前,让我们花一点时间来回顾涉及的各种概念。如果您已经熟悉 Docker 概念,如卷、链接和端口转发,那么您可能希望直接跳到下一节。
Docker 镜像
每个 Docker 容器都是 Docker 镜像的本地实例。您可以将 Docker 镜像视为完整的 Linux 安装。通常,最小安装仅包含运行镜像所需的最低限度的软件包。这些镜像使用主机系统的内核,但由于它们运行在 Docker 容器内部并且只能看到自己的文件系统,因此完全可以在 Ubuntu 主机上运行 CentOS 发行版(反之亦然)。
大多数 Docker 镜像都是通过 Docker Hub 分发的,该镜像由 Docker 团队维护。大多数流行的开源项目都有对应的镜像上传到 Docker Registry,您可以使用这些镜像来部署软件。在可能的情况下,最好获取“官方”镜像,因为它们由 Docker 团队保证遵循 Docker 最佳实践。
Docker 镜像之间的通信
Docker 容器与主机机器隔离,这意味着默认情况下主机机器无法访问 Docker 容器内部的文件系统,也无法通过网络与其通信。这可能会使配置和处理在 Docker 容器内部运行的镜像变得困难。
Docker 有三种主要方法来解决这个问题。第一种最常用的方法是让 Docker 指定环境变量,这些环境变量将在 Docker 容器内部设置。然后,Docker 容器内部运行的代码将在启动时检查这些环境变量的值,并使用它们来正确配置自身。
另一种常用的方法是 Docker 数据卷。Docker 卷有两种类型 — 内部和共享。
指定内部卷只意味着对于您为特定 Docker 容器指定的文件夹,当容器被移除时数据将被持久化。例如,如果您希望确保日志文件持久化,您可以指定一个内部的 /var/log
卷。
共享卷将 Docker 容器内的文件夹映射到主机机器上的文件夹。这允许您轻松地在 Docker 容器和主机机器之间共享文件。
与 Docker 容器通信的第三种方法是通过网络。Docker 允许不同的 Docker 容器之间通过 links
进行通信,以及端口转发,允许您将 Docker 容器内部的端口转发到主机服务器上的端口。例如,您可以创建一个链接,允许您的 WordPress 和 MariaDB Docker 容器相互通信,并使用端口转发将 WordPress 暴露给外部世界,以便用户可以连接到它。
先决条件
要遵循本文,您将需要以下内容:
- 安装了非 root 用户并具有 sudo 权限的 CentOS 7 服务器(有关详细信息,请参见 CentOS 7 上的初始服务器设置)
- 使用《如何在 CentOS 7 上安装和使用 Docker》中的步骤 1 和步骤 2 安装了 Docker
一旦这些准备就绪,您就可以开始跟随操作了。
步骤 1 — 安装 Docker Compose
为了获取最新版本,遵循 Docker 文档的指导,从 Docker 的 GitHub 仓库中安装 Docker Compose 二进制文件。
检查当前版本,如果需要,更新以下命令中的版本:
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
接下来,设置权限以使二进制文件可执行:
sudo chmod +x /usr/local/bin/docker-compose
然后,通过检查版本来验证安装是否成功:
docker-compose --version
这将打印出您安装的版本:
docker-compose version 1.23.2, build 1110ad01
现在,您已经安装了 Docker Compose,可以准备运行一个“Hello World”示例了。
步骤 2 — 使用 Docker Compose 运行容器
公共 Docker 注册表 Docker Hub 包含一个简单的“Hello World”镜像,用于演示和测试。它展示了使用 Docker Compose 运行容器所需的最小配置:一个调用单个镜像的 YAML 文件。
首先,为我们的 YAML 文件创建一个目录:
mkdir hello-world
然后切换到该目录:
cd hello-world
现在使用你喜欢的文本编辑器创建 YAML 文件。本教程将使用 Vi:
vi docker-compose.yml
进入插入模式,按 i
键,然后将以下内容放入文件中:
my-test: image: hello-world
第一行将成为容器名称的一部分。第二行指定要使用哪个镜像来创建容器。当你运行 docker-compose up
命令时,它将查找本地镜像,名称为 hello-world
。
完成后,按 ESC
退出插入模式。输入 :x
然后 ENTER
保存并退出文件。
要手动查看系统上的镜像,使用 docker images
命令:
docker images
当没有本地镜像时,只会显示列标题:
REPOSITORY TAG IMAGE ID CREATED SIZE
现在,仍然在 ~/hello-world
目录中,执行以下命令创建容器:
docker-compose up
第一次运行该命令时,如果没有名为 hello-world
的本地镜像,Docker Compose 将从 Docker Hub 公共仓库中拉取它:
Pulling my-test (hello-world:)... latest: Pulling from library/hello-world 1b930d010525: Pull complete . . .
拉取镜像后,docker-compose
将创建一个容器,附加并运行 hello 程序,从而确认安装似乎正常工作:
. . . Creating helloworld_my-test_1... Attaching to helloworld_my-test_1 my-test_1 | my-test_1 | Hello from Docker. my-test_1 | This message shows that your installation appears to be working correctly. my-test_1 | . . .
然后它将打印它所做的解释:
. . . my-test_1 | To generate this message, Docker took the following steps: my-test_1 | 1. The Docker client contacted the Docker daemon. my-test_1 | 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. my-test_1 | (amd64) my-test_1 | 3. The Docker daemon created a new container from that image which runs the my-test_1 | executable that produces the output you are currently reading. my-test_1 | 4. The Docker daemon streamed that output to the Docker client, which sent it my-test_1 | to your terminal. . . .
Docker 容器只在命令活动时运行,因此一旦 hello
运行结束,容器就会停止。因此,当你查看活动进程时,列标题将显示,但 hello-world
容器不会列出,因为它没有运行:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
使用 -a
标志显示所有容器,而不仅仅是活动的:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 50a99a0beebd hello-world "/hello" 3 minutes ago Exited (0) 3 minutes ago hello-world_my-test_1
现在你已经测试了运行容器,可以继续探索一些基本的 Docker Compose 命令。
步骤 3 — 学习 Docker Compose 命令
为了让你开始使用 Docker Compose,本节将介绍 docker-compose
工具支持的一般命令。
docker-compose
命令是基于每个目录的。你可以在一台机器上运行多个 Docker 容器组 — 只需为每个容器创建一个目录和一个 docker-compose.yml
文件。
到目前为止,你一直在自己运行 docker-compose up
,可以使用 CTRL-C
关闭容器。这允许在终端窗口中显示调试消息。但这并不理想;在生产环境中,更健壮的做法是让 docker-compose
更像一个服务。一种简单的方法是在启动会话时添加 -d
选项:
docker-compose up -d
docker-compose
现在将在后台运行。
要显示你的 Docker 容器组(已停止和当前运行的),使用以下命令:
docker-compose ps -a
如果容器已停止,State
将显示为 Exited
,如下例所示:
Name Command State Ports ------------------------------------------------ hello-world_my-test_1 /hello Exit 0
运行中的容器将显示 Up
:
Name Command State Ports --------------------------------------------------------------- nginx_nginx_1 nginx -g daemon off; Up 443/tcp, 80/tcp
要停止应用程序组的所有运行中的 Docker 容器,可以在与用于启动 Docker 组的 docker-compose.yml
文件相同的目录中发出以下命令:
docker-compose stop
在某些情况下,Docker 容器将在内部卷中存储其旧信息。如果你想从头开始,可以使用 rm
命令完全删除组成你的容器组的所有容器:
docker-compose rm
如果你尝试从包含 Docker 容器和 .yml
文件的目录之外的目录运行这些命令,它将返回错误:
ERROR: Can't find a suitable configuration file in this directory or any parent. Are you in the right directory? Supported filenames: docker-compose.yml, docker-compose.yaml
本节介绍了如何使用 Docker Compose 操纵容器的基础知识。如果你需要更好地控制你的容器,你可以访问 Docker 容器的文件系统,并从容器内部的命令提示符中工作,这个过程将在下一节中描述。
步骤 4 — 访问 Docker 容器文件系统
为了在容器内部的命令提示符下工作并访问其文件系统,您可以使用 docker exec
命令。
“Hello World” 示例在运行后退出,因此为了测试 docker exec
,启动一个将保持运行的容器。在本教程中,使用 Docker Hub 上的 Nginx 镜像。
创建一个名为 nginx
的新目录并进入该目录:
mkdir ~/nginx cd ~/nginx
接下来,在新目录中创建一个 docker-compose.yml
文件并在文本编辑器中打开它:
vi docker-compose.yml
然后,在文件中添加以下行:
nginx: image: nginx
保存并退出文件。使用以下命令将 Nginx 容器作为后台进程启动:
docker-compose up -d
Docker Compose 将下载 Nginx 镜像,并且容器将在后台启动。
现在,您需要容器的 CONTAINER ID
。使用以下命令列出所有正在运行的容器:
docker ps
您将看到类似以下内容:
[secondary_label Output of `docker ps`] CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b86b6699714c nginx "nginx -g 'daemon of…" 20 seconds ago Up 19 seconds 80/tcp nginx_nginx_1
如果您想要更改此容器内的文件系统,您需要获取其 ID(在本例中为 b86b6699714c
),然后使用 docker exec
在容器内启动一个 shell:
docker exec -it b86b6699714c /bin/bash
-t
选项打开一个终端,-i
选项使其交互式。/bin/bash
打开一个 bash shell 到运行中的容器。
然后,您将看到类似于容器的 bash 提示符:
root@b86b6699714c:/#
从这里,您可以在容器内部的命令提示符下工作。但是请记住,除非您在保存为数据卷的目录中,否则您的更改将在容器重新启动时消失。另外,请记住,大多数 Docker 镜像都是使用非常精简的 Linux 安装创建的,因此您习惯使用的一些命令行实用程序和工具可能不存在。
结论
您现在已经安装了 Docker Compose,并通过运行“Hello World”示例测试了您的安装,并探索了一些基本命令。
虽然“Hello World”示例确认了您的安装,但简单的配置并未展示 Docker Compose 的主要优势之一 — 能够同时启动和关闭一组 Docker 容器。要查看 Docker Compose 的强大功能,请参阅《如何使用 Docker Compose 保护基于 Node.js 的容器化应用程序,使用 Nginx、Let’s Encrypt 和 Docker Compose》和《如何在 Ubuntu 16.04 上使用 Docker 和 Docker Compose 配置持续集成测试环境》。尽管这些教程是针对 Ubuntu 16.04 和 18.04 的,但这些步骤也可以适用于 CentOS 7。