使用 Docker 图像和 docker-compose 构建 CICD 管道的正确方法
Proper way to build a CICD pipeline with Docker images and docker-compose
我有一个关于 DockerHub 和 GitHub 的一般性问题。我正在尝试使用 AWS 实例在 Jenkins 上构建管道,我的最终目标是部署 docker-compose.yml
我在 GitHub 上的回购具有:
version: "3"
services:
db:
image: postgres
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- ./tmp/db:/var/lib/postgresql/data
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_HOST: db
我在 CI/CD 管道中读到人们构建他们的图像并将它们推送到 DockerHub,但它有什么意义?
你只会推送一个单独的图像。即使您稍后在不同的实例中拉取图像,为了 运行 具有不同服务的应用程序,您将需要 运行 使用 docker-compose
的容器,而您不会拥有它除非您再次从 github 存储库中提取它或在管道上创建它,对吗?
从 Github 获取存储库并执行 docker-compose
命令不是更好更直接吗?有没有一种“更清洁”或“正确”的方法呢?提前致谢!
您应该需要复制到远程系统的唯一 文件是docker-compose.yml
文件。甚至这在技术上也是可选的,因为 Compose 只是包装了基本的 Docker 命令;您可以手动 docker network create
然后 docker run
这两个容器,根本不复制任何内容。
对于此设置,重要的是删除 volumes:
需要应用程序代码的副本来覆盖图像的内容。您也不应该需要覆盖 command:
。对于部署,您需要将 build:
替换为 image:
.
version: "3.8"
services:
db: *from-the-question
web:
image: registry.example.com/me/web:${WEB_TAG:-latest}
ports:
- "3000:3000"
depends_on:
- db
environment: *web-environment-from-the-question
# no build:, command:, volumes:
在 Compose 设置中,您可以 put the build:
configuration in a parallel docker-compose.override.yml
file 不会将其复制到部署系统。
那又怎样?以这种方式构建事物有几个很好的理由。
一个 forward-looking 答案涉及集群容器管理器,例如 Kubernetes、Nomad 或亚马逊的专有 ECS。在这些容器中,运行s 位于无法区分的机器集群中的某个位置,仅 复制应用程序代码的方法是从注册表中提取它。在这些设置中,您不会在任何地方复制任何文件,而是向集群管理器发出指令,说明图像的一些副本应该 运行 某处。
另一个很好的理由是支持回滚应用程序。在上面的 Compose 片段中,我引用了一个环境变量 ${WEB_TAG}
。假设您每天推出一个版本,并给每个版本一个 date-stamped 标签; registry.example.com/me/web:20220220
。但是,今天的构建出了点问题!当你弄明白的时候,你可以连接到部署机器和运行
WEB_TAG=20220219 docker-compose up -d
并立即回滚,再次不尝试签出任何内容或复制应用程序。
一般来说,使用 Docker,您希望将图像制作成 self-contained 的样子,尽管仍然承认有些东西无法“烘焙”,例如数据库凭据在”。所以确保 COPY
中的代码,不要用 volumes:
覆盖代码,请设置一个合理的 CMD
。您应该能够从一个只安装 Docker 而没有其他任何东西的干净系统开始,并且 docker run
图像只需要 Docker-related 设置。您可以想象为 运行 docker
命令编写 shell 脚本,而 docker-compose.yml
文件只是该文件的声明版本。
最后记住你没有使用Docker。您可以使用 general-purpose system-management 工具(如 Ansible、Salt Stack 或 Chef)将 Ruby 安装到目标机器上并手动复制代码。这是一种 well-proven 部署方法。我发现 Docker 更简单,但假设代码及其所有依赖项实际上都在映像中,不需要单独复制。
我有一个关于 DockerHub 和 GitHub 的一般性问题。我正在尝试使用 AWS 实例在 Jenkins 上构建管道,我的最终目标是部署 docker-compose.yml
我在 GitHub 上的回购具有:
version: "3"
services:
db:
image: postgres
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- ./tmp/db:/var/lib/postgresql/data
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_HOST: db
我在 CI/CD 管道中读到人们构建他们的图像并将它们推送到 DockerHub,但它有什么意义?
你只会推送一个单独的图像。即使您稍后在不同的实例中拉取图像,为了 运行 具有不同服务的应用程序,您将需要 运行 使用 docker-compose
的容器,而您不会拥有它除非您再次从 github 存储库中提取它或在管道上创建它,对吗?
从 Github 获取存储库并执行 docker-compose
命令不是更好更直接吗?有没有一种“更清洁”或“正确”的方法呢?提前致谢!
您应该需要复制到远程系统的唯一 文件是docker-compose.yml
文件。甚至这在技术上也是可选的,因为 Compose 只是包装了基本的 Docker 命令;您可以手动 docker network create
然后 docker run
这两个容器,根本不复制任何内容。
对于此设置,重要的是删除 volumes:
需要应用程序代码的副本来覆盖图像的内容。您也不应该需要覆盖 command:
。对于部署,您需要将 build:
替换为 image:
.
version: "3.8"
services:
db: *from-the-question
web:
image: registry.example.com/me/web:${WEB_TAG:-latest}
ports:
- "3000:3000"
depends_on:
- db
environment: *web-environment-from-the-question
# no build:, command:, volumes:
在 Compose 设置中,您可以 put the build:
configuration in a parallel docker-compose.override.yml
file 不会将其复制到部署系统。
那又怎样?以这种方式构建事物有几个很好的理由。
一个 forward-looking 答案涉及集群容器管理器,例如 Kubernetes、Nomad 或亚马逊的专有 ECS。在这些容器中,运行s 位于无法区分的机器集群中的某个位置,仅 复制应用程序代码的方法是从注册表中提取它。在这些设置中,您不会在任何地方复制任何文件,而是向集群管理器发出指令,说明图像的一些副本应该 运行 某处。
另一个很好的理由是支持回滚应用程序。在上面的 Compose 片段中,我引用了一个环境变量 ${WEB_TAG}
。假设您每天推出一个版本,并给每个版本一个 date-stamped 标签; registry.example.com/me/web:20220220
。但是,今天的构建出了点问题!当你弄明白的时候,你可以连接到部署机器和运行
WEB_TAG=20220219 docker-compose up -d
并立即回滚,再次不尝试签出任何内容或复制应用程序。
一般来说,使用 Docker,您希望将图像制作成 self-contained 的样子,尽管仍然承认有些东西无法“烘焙”,例如数据库凭据在”。所以确保 COPY
中的代码,不要用 volumes:
覆盖代码,请设置一个合理的 CMD
。您应该能够从一个只安装 Docker 而没有其他任何东西的干净系统开始,并且 docker run
图像只需要 Docker-related 设置。您可以想象为 运行 docker
命令编写 shell 脚本,而 docker-compose.yml
文件只是该文件的声明版本。
最后记住你没有使用Docker。您可以使用 general-purpose system-management 工具(如 Ansible、Salt Stack 或 Chef)将 Ruby 安装到目标机器上并手动复制代码。这是一种 well-proven 部署方法。我发现 Docker 更简单,但假设代码及其所有依赖项实际上都在映像中,不需要单独复制。