1. 概述
Docker 是一个方便的容器化工具。它如此有用,以至于有时我们希望在项目中拥有不止一个 Dockerfile。不幸的是,这与命名所有 Dockerfile 只为“Dockerfile”的简单约定相冲突。
在这篇教程中,我们将探讨如何绕过这一限制,并保持项目结构的整洁。
2. Dockerfile
Dockerfile 是一个包含构建 Docker 映像所需的所有指令的文件。Docker 可以自动使用它来构建映像,而无需任何额外的命令或参数。由于命名约定,我们甚至不需要(直到版本 1.8.0,实际上我们无法)指定文件路径。
我们可以从 Dockerfile 所在目录调用 Docker 的 build
命令:
$ docker build .
3. 指定 Dockerfile 名称
从版本 1.8.0 开始,我们可以通过使用 -f
参数将 Dockerfile 的名称更改并传递给 build
命令。假设我们有两个 Dockerfile,一个用于构建后端,另一个用于构建前端。
我们可以适当地命名它们,并分别调用两次 build
命令,每次传递一个 Dockerfile 的名称:
$ docker build -f Dockerfile.frontend .
...
$ docker build -f Dockerfile.backend .
这种解决方案工作良好,但有一些不方便的缺点。第一个是需要单独为每个文件调用 build
命令。对于两个文件来说这并不是太糟糕,但如果我们的组件更多,它可能会迅速产生需要额外构建脚本的需求。第二个缺点是,一些集成开发环境可能因为偏离了约定而感到困惑,并停止提供语法高亮。
4. 使用 docker-compose
与其更改 Dockerfile 的名称,我们可以将它们放在不同的文件夹中。然后,我们可以使用 docker-compose 来触发所有文件的构建。假设我们有一个类似于以下的目录结构:
docker-compose.yml
docker
├── frontend
│ └── Dockerfile
└── backend
└── Dockerfile
通常,docker-compose
文件最基本的用途意味着从仓库使用图像,我们也可以提供目录路径来用于 build
:
version: '3'
services:
frontend:
build: ./docker/frontend
ports:
- "8081:8081"
backend:
build: ./docker/backend
ports:
- "8080:8080"
现在运行 docker-compose
将会从 Dockerfile 构建图像:
$ docker-compose up
此外,在一个 docker-compose
文件中,我们可以放入使用不同方式创建图像的服务。有些可以从我们的源代码构建,其他则可以由外部注册表提供。例如,我们可能想要构建后端图像,但获取公共注册表中的数据库图像:
services:
backend:
build: ./docker/backend
ports:
- "8080:8080"
postgres:
image: 'postgres:latest'
现在,docker-compose
不仅会构建我们的服务并运行它们,还会为我们提供数据库。
5. 结论
在这篇教程中,我们学习了处理一个项目中多个 Dockerfile 的两种不同策略。
第一种基于更改不同 Dockerfile 的名称,提供了快速且优雅地解决问题的方法。第二种依赖于 docker-compose
并提供了构建过程的结构化和自动化选项。