使用 Docker Compose 让 Docker 更加强大
目录
当我们开始使用 Docker,一般会使用 Docker 命令来运行和管理单个的容器。但是,当我们的应用变得越来越复杂,包含多个互相关联的容器时,使用 Docker 命令就变得不太方便了。这时,我们就需要使用 Docker Compose。
Docker Compose 是什么 #
Docker Compose 是用于定义和运行多容器Docker 应用程序的工具。 在Compose 中,可以使用YAML 文件来配置应用程序的服务。 然后,运行一条命令,即可从配置中创建并启动所有服务。 使用Compose 可在一台主计算机上方便地协调多个容器映像。Docker Compose 将多容器应用的管理简化了,让 Docker 变得更加强大。它在以下情况下特别有用:
- 多容器应用:如果你的应用由多个服务组成,例如一个前端服务和一个后端服务,或者一个数据库服务和一个 web 服务,那么 Docker Compose 是管理这些服务的理想工具。你可以在一个 YAML 文件中定义所有的服务,并且只需要一条命令就可以启动所有的服务。
- 服务关联:在复杂的应用中,不同的服务之间可能需要互相通信。例如,一个 web 服务可能需要连接到数据库服务。使用 Docker Compose,你可以很容易地在 YAML 文件中定义这些服务之间的关联。
- 开发和测试环境:在开发和测试阶段,我们经常需要快速地启动和停止应用。Docker Compose 使得这个过程变得简单快速。你可以一次性启动你的应用的所有部分,进行开发或测试,然后一次性停止所有的服务。
总的来说,如果你的应用包含多个服务,这些服务需要互相通信,或者你需要在多个环境中运行你的应用,那么 Docker Compose 将会是你的最佳选择。
安装 Docker Compose #
在之前的 Docker 101 安装 Docker 的部分已经包含了 Docker Compose 的安装,可以快速运行下面的命令检查安装是否完成:
docker compose version
如果 terminal 能正常输出版本号则安装顺利完成,如若不是,还请根据上一篇文章重新安装一次。
理解 Compose 文件 #
Docker Compose 使用 YAML 文件来定义多容器应用的服务,这个文件通常被称为 Compose 文件。Compose 文件中定义的每一项服务都将运行在一个独立的容器中。
Compose 文件的基本结构如下:
version: "3"
services:
service1:
image: image1
service2:
build: .
ports:
- "5000:5000"
service3:
image: image3
volumes:
- /data
主要元素包括:
- version:这是你使用的 Docker Compose 文件格式的版本。通常,我们应该使用最新的版本。
- services:这里列出了你的应用中的所有服务。每个服务都运行在一个独立的容器中。
- image:这是服务使用的 Docker 镜像。你可以使用任何在 Docker Hub 上可用的镜像,也可以使用你自己创建的镜像。
- build:如果你的服务需要从 Dockerfile 构建镜像,你可以在这里指定 Dockerfile 所在的路径。
- ports:这里你可以定义端口映射。格式是
: 。 - volumes:你可以在这里定义数据卷。数据卷可以用于在容器之间共享数据,或者在容器和宿主机之间共享数据。
让我们通过一个简单的 Compose 文件来加深理解。假设我们有一个 web 应用,它包含一个 web 服务和一个数据库服务,对应的 Compose 文件可能如下:
version: "3"
services:
web:
image: my-web-app:latest
ports:
- "8000:8000"
networks:
- appnet
db:
image: postgres:latest
volumes:
- db-data:/var/lib/postgresql/data
networks:
- appnet
networks:
appnet:
volumes:
db-data:
以上的 Compose 文件定义了两个服务:web 和 db。web 服务使用的是我们自己创建的镜像,映射了 8000 端口。db 服务使用的是官方的 postgres 镜像,定义了一个名为 db-data 的数据卷。web 服务和 db 服务共享一个名为 appnet 的网络,因此它们可以直接通信。
运行你的第一个 Docker Compose 项目 #
为了简洁起见,我们将创建一个包含两个服务的应用:一个简单的 Node.js Web 服务和一个 Redis 服务。
首先,我们创建一个 Node.js Web 服务。在你的项目目录中创建一个名为 app.js
的文件,并添加以下内容:
const express = require('express');
const redis = require('redis');
const client = redis.createClient({host: 'redis'});
const app = express();
app.get('/', (req, res) => {
client.incr('visits', (err, visits) => {
res.send(`Number of visits: ${visits}`);
});
});
app.listen(8080, () => {
console.log('Listening on port 8080');
});
这个 Node.js 应用将会连接到 Redis 服务,并在每次接收到 HTTP GET 请求时,将 Redis 中的 ‘visits’ 键的值加一。
然后,我们需要创建一个 Dockerfile 来定义如何构建我们的 Node.js 应用的 Docker 镜像。在你的项目目录中创建一个名为 Dockerfile
的文件,并添加以下内容:
FROM node:14
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["node", "app.js"]
接下来,我们需要创建一个 package.json
文件来定义我们的 Node.js 应用的依赖:
{
"name": "docker-compose-example",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.17.1",
"redis": "^3.1.2"
}
}
最后,我们创建 docker-compose.yml
文件来定义我们的服务:
version: '3'
services:
web:
build: .
ports:
- "8080:8080"
redis:
image: "redis:alpine"
现在,我们的项目结构应该如下:
.
├── Dockerfile
├── app.js
├── docker-compose.yml
└── package.json
现在,你可以运行 docker-compose up
来启动你的应用。你应该能在浏览器中通过访问 http://localhost:8080 来查看你的 Node.js 应用。每次刷新页面,你会看到访问次数增加,这就是我们的 Redis 服务在起作用。
Compose 命令和操作 #
Docker Compose 拥有一套丰富的命令集合,使我们可以轻松地管理和操作我们的应用。这里我们来介绍一些最常用的命令:
- docker-compose up:这个命令是用来启动你的 Docker Compose 应用的。默认情况下,它会创建并启动定义在
docker-compose.yml
文件中的所有服务。如果你加上 -d 参数(即docker-compose up -d
),那么这个命令将会在后台运行你的应用,这在生产环境中特别有用。 - docker-compose down:这个命令会停止并删除你的 Docker Compose 应用,包括应用的网络和卷。如果你加上 -v 参数(即
docker-compose down -v
),那么它会同时删除你的应用的匿名卷。 - docker-compose ps:这个命令会显示你的 Docker Compose 应用的状态。它会列出你的应用中所有的服务,以及它们当前的状态,如是否在运行,开放的端口等。
- docker-compose logs:这个命令会显示你的 Docker Compose 应用的日志。默认情况下,它会显示所有服务的日志,但是你可以指定一个特定的服务来查看它的日志(如
docker-compose logs web
)。 - docker-compose build:这个命令会构建或者重新构建你的服务。如果你的服务使用了 build 参数来指定
Dockerfile
的位置,那么这个命令将会使用Dockerfile
来构建你的服务的镜像。
以上只是 Docker Compose 命令的冰山一角。还有很多其他的命令,如 docker-compose restart
(用于重启服务)、docker-compose pull
(用于从 Docker Hub 下载镜像)等等。我建议你查阅 Docker Compose 的官方文档,以获取更详细的信息。
在 Compose 中使用环境变量 #
环境变量是在编写可移植和可伸缩的应用时的关键组成部分。Docker Compose 支持在 docker-compose.yml
文件中使用环境变量。你可以在配置文件中直接定义环境变量,也可以从环境变量文件中读取。
在我们的例子中,让我们假设我们的 Node.js 应用需要一个环境变量 NODE_ENV
来决定运行的环境,我们还假设 Redis 服务需要一个环境变量 REDIS_PASSWORD
作为密码。
直接在配置文件中定义环境变量 #
在 docker-compose.yml
文件中,我们可以在 environment
部分定义环境变量,例如:
version: '3'
services:
web:
build: .
ports:
- "8080:8080"
environment:
- NODE_ENV=production
redis:
image: "redis:alpine"
environment:
- REDIS_PASSWORD=secretpassword
在上面的例子中,我们为 web 服务设置了环境变量 NODE_ENV
的值为 production,同时为 redis 服务设置了环境变量 REDIS_PASSWORD
的值为 secretpassword。
从环境变量文件中读取 #
Docker Compose 也支持从 .env
文件中读取环境变量。默认情况下,Docker Compose 将会在 docker-compose.yml
文件所在的目录中查找 .env
文件。
让我们创建一个 .env
文件,并在其中定义我们的环境变量:
NODE_ENV=production
REDIS_PASSWORD=secretpassword
然后,我们在 docker-compose.yml
文件中引用这些环境变量:
version: '3'
services:
web:
build: .
ports:
- "8080:8080"
environment:
- NODE_ENV
redis:
image: "redis:alpine"
environment:
- REDIS_PASSWORD
在这个例子中,Docker Compose 将会从 .env 文件中读取 NODE_ENV
和 REDIS_PASSWORD
的值,并将它们设置为对应服务的环境变量。
使用环境变量,可以轻松地配置和调整应用的行为,无论是在开发环境,还是在生产环境。在 Docker Compose 中使用环境变量,让应用更加灵活和可配置。
Docker Compose 的最佳实践 #
使用 Docker Compose 的过程中,有一些最佳实践可以帮助我们更高效、更安全地使用它。
- 使用 .env 文件:
.env
文件是一个很好的方式来管理你的环境变量。你可以将所有敏感的和特定于环境的配置项(例如,数据库密码,API 密钥等)存储在这个文件中,并在docker-compose.yml
文件中引用它们。这样,你的docker-compose.yml
文件可以不包含任何敏感信息,更便于共享和版本控制。 - 使用版本控制系统: 将
docker-compose.yml
文件和相关的Dockerfile
一起存储在版本控制系统(例如 Git)中。这样可以帮助你追踪历史变更,也可以让其他开发者更容易地参与到项目中来。 - 利用 Compose 文件的可扩展性: Docker Compose 允许你使用多个 Compose 文件来定义你的应用。这使得你可以有一个基础的 Compose 文件定义你的主要服务,然后使用额外的 Compose 文件来定义开发环境、测试环境和生产环境的特定配置。
- 定义健康检查: 你可以在
docker-compose.yml
文件中为你的服务定义健康检查。这可以帮助 Docker 确定你的服务是否正常运行。如果服务出现问题,Docker 可以自动重启它,或者停止依赖于它的其他服务。 - 使用服务的依赖性: Docker Compose 允许你定义服务之间的依赖关系。例如,如果你的 web 服务依赖于数据库服务,你可以在
docker-compose.yml
文件中明确指定这种依赖关系。这样,Docker Compose 会确保在启动 web 服务之前先启动数据库服务。
总结 #
Docker Compose 是一个非常强大的工具,它使得定义和管理多容器 Docker 应用变得简单。虽然文章已经覆盖了许多内容,但 Docker Compose 的功能还远不止于此。在例子中,我只使用了 Compose 的一部分功能。在实际的项目中,你可能还需要处理日志,搭建持续集成/持续部署(CI/CD)环境,以及处理更复杂的网络和卷配置等问题。
希望这篇文章能够帮助你开始使用 Docker Compose,并在你的开发旅程中为你带来帮助。如果你有任何问题或者反馈,随时欢迎向我反馈。