我有一个关于 DockerHub 和 GitHub 的一般性问题。我正在尝试使用 AWS 实例在 Jenkins 上构建管道,我的最终目标是部署我在 GitHub 上的存储库具有的
docker-compose.yml
:
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 设置中,您可以 将
build:
配置放入并行 docker-compose.override.yml
文件中,该文件不会被复制到部署系统。
那又怎样? 以这种方式构建事物有几个很好的理由。
前瞻性的答案涉及集群容器管理器,例如 Kubernetes、Nomad 或 Amazon 专有的 ECS。 在这些容器中,容器在无法区分的机器集群中的某个位置运行,而复制应用程序代码的“唯一”方法是从注册表中提取它。 在这些设置中,您不会在任何地方复制任何文件,而是向集群管理器发出指令,指示应在某处运行一定数量的映像副本。 另一个很好的理由是支持回滚应用程序。 在上面的 Compose 片段中,我引用了一个环境变量
${WEB_TAG}
。 假设您每天推出一个版本,并给每个版本一个带有日期标记的标签;
registry.example.com/me/web:20220220
。 但是,今天的构建出了点问题! 当你弄清楚后,你可以连接到部署机器并运行WEB_TAG=20220219 docker-compose up -d
并立即回滚,再次无需尝试检查任何内容或复制应用程序。
一般来说,使用 Docker,您希望使映像尽可能独立,但仍然承认有些东西(例如数据库凭据)无法“嵌入”。 因此,请确保
COPY
中的代码,不要用
volumes:
覆盖代码,请设置合理的 CMD
。 您应该能够从一个仅安装了 Docker 而没有其他任何东西的干净系统开始,并且 docker run
镜像仅包含与 Docker 相关的设置。 您可以想象编写一个 shell 脚本来运行 docker
命令,而 docker-compose.yml
文件只是该脚本的声明性版本。
最后记住,您没有使用Docker。 您可以使用 Ansible、Salt Stack 或 Chef 等通用系统管理工具将 Ruby 安装到目标计算机上,并手动复制代码。 这是一种经过充分验证的部署方法。 我发现 Docker 更简单,但假设代码及其所有依赖项实际上都在映像中,不需要单独复制。