Docker Compose 何时在构建上使用图像

Docker Compose when to use image over build

Docker Compose documentation, and its example use case 非常适合找出拆分不同工作环境(开发、生产等)的各种可能性。

web:
  image: example/my_web_app:latest
  links:
    - db
    - cache

db:
  image: postgres:latest

cache:
  image: redis:latest

但是,我不太清楚何时在构建时使用图像。

这是他们唯一的 image: example/my_web_app:latest 示例的唯一可用描述:

Another common use case is running adhoc or administrative tasks against one or more services in a Compose app. This example demonstrates running a database backup.

其余示例案例使用 build: .

我知道在第一次启动容器时使用图像而不是构建可以提供更好的性能,因为图像已经准备好构建。但是,我可以预见这样做的很多问题:

前面的一些观点可能并不完全正确。随意拆卸它们。

通常您会希望在以下情况下使用 build .

  • 发展
  • 自动化测试

这通常在您正在开发或测试并且代码尚未准备好生产时完成。例如测试失败,代码无法编译,代码错误等

通常情况下,您只会在准备好交付部署时创建映像。那时您将创建图像,通过其标签对其进行版本更新并将其推送到您的个人 DTR 或 Docker Hub。

当使用 docker compose 中的版本时,您不受 :latest 的约束,您可以指定您想要的任何版本以确保在任何给定环境中正确的版本是 运行ning .例如,在生产环境中,您可能希望创建一个名为 docker-production.yaml 的组合文件,其配置如下:

web:
  image: "example/my_web_app:${TAG}"
  links:
    - db
    - cache
db:
  image: postgres:9.5.2
cache:
  image: redis:3.0.7

其中 ${TAG} 是在 运行 时被替换的环境变量,例如docker-compose up -d -f docker-production.yaml。您可以阅读有关变量替换的更多信息 here.

compose 的强大之处在于,您可以使用构建系统自动启动的变量替代来创建构建文件,不再局限于 :latest 甚至硬编码版本。

注:

  1. 团队 运行 他们的构建、发布和部署方式因他们而异 弄清楚什么最适合他们和他们的产品所以上面 build . 场景可能并不适用于所有情况,但 准确说明我公司如何使用 compose。
  2. 这假设 build .docker-compose context 而不是 docker build 上下文中。

正如@GHETTO.CHiLD所说,这取决于您的需求和您的工作流程。实际上我们不执行手动构建。我将解释我们如何管理这个以及为什么。它非常适合我们的流程,但可能不适合其他场景。

  • 我们不手动构建图像。 CI 做到了(在我们的例子中是 GitLab CI
  • 我们有 2 种图像,development/testingproduction
  • 有一个 docker-compose.yml 用于简化环境管理的开发。他们只是 运行 docker-compose up 并且它从注册表中提取图像并将其目录安装在容器中。

    version: "2"
    
    services:
      web:
        build: 
          context: ../../
          dockerfile: dockerfiles/dev/Dockerfile
        image: registry.my.domain/my_image:dev
        volumes:
          - ../../:/opt/app
        working_dir: /opt/app
    
  • 如果他们对 Dockerfile 进行了更改(例如,他们需要一个新的库),他们可以在他们的机器上构建镜像 (docker-compose build),但不会推送镜像针对注册表。

  • 当他们高兴时,他们会推送新代码(包括 Dockerfile),然后 CI 构建新的 dev 图像和 运行 测试。
  • CI 每次都在同一台主机上构建图像,因此可以利用缓存。如果 Dockerfile 没有变化,构建时间不到一秒。
  • 创建新标签时,CI 构建一个生产镜像,使用 $TAG 作为镜像标签。
  • 对于生产,我们使用 orchestrator,而不是 Compose YAML。我们不想存储项目存储库中 docker-compose.yml 中的敏感数据。要升级,我们只需从注册表中提取新标签(我们可以自动执行此操作,但我还没有信心在没有人工测试的情况下部署到生产环境:D)。

开发时当然可以每次都构建镜像,但是有些项目可能需要很长时间构建。例如,Python3 + pandas 可能需要 25 分钟才能构建,因此如果您必须经常在项目之间切换,那将是令人沮丧的。另一方面,拉取镜像只需不到一分钟。

我们使用这种方法是因为 GitLab 为我们提供了 CI、注册表和 运行 人员来构建图像和 运行 测试。没有它你也可以做到,但你需要自己集成所有组件。流程并不完美,它有一些缺点,但在我们的场景中是次要的。