Docker Compose - 是否可以使用单个命令更新所有更改的图像?

问题描述 投票:0回答:3

我有一个像这样的compose.yml

version: '3.7'

services:
    nginx:
        restart: unless-stopped
        image: ghcr.io/user/frontend:latest
        ports:
            - 80:80
        depends_on: 
            - backend
    backend:
        restart: unless-stopped
        image: ghcr.io/user/backend:latest
        entrypoint: /home/app/web/wsgi-entrypoint.sh
        expose:
            - 8000   

我们在 Github 上存储了 2 个图像:前端和后端。

我的目标是:当 Github Docker 注册表上更新了镜像时,我想自动更新服务器上的镜像,并通过 docker-compose 启动新镜像来替换旧镜像。

例如:我有一个由前端和后端组成的正在运行的组合,但我刚刚推送了一个新图像:ghcr.io/user/frontend:latest

现在,我想要一个命令,仅更新已更改的图像(在本例中为ghcr.io/user/frontend:latest),当我重新加载前端网页时,我会看到更改。

我的尝试如下:

docker-compose up -d --build

但是系统说:

compose-backend_1 is up-to-date
compose-nginx_1 is up-to-date

这不是真的!

所以,我使用的工作程序有点手动:

docker pull ghcr.io/user/frontend:latest

我在控制台中看到:状态:已下载较新图像, 这是新图像已下载的证明。 然后,如果我重新启动相同的命令,控制台将显示:Status: Image is up to date for ghcr.io/user/frontend:latest

最后:

docker-compose up -d --build

说:重新创建 compose-nginx_1 ... 完成

我想命令 docker-compose up -d --build ALONE 不寻找新图像,因此不会更新已更改的图像。

那么,是否有一个特定的命令可以解决这个问题?

docker docker-compose
3个回答
1
投票

应该通过运行

docker-compose pull
,然后运行
docker-compose up -d
来实现 或者,更短:
docker-compose up -d --pull always


0
投票

您可以在 docker-compose.yml 文件中的许多地方使用

变量替换
,特别是包括
image:
。如果您为每个构建提供唯一的标签,那么您可以将该标签作为环境变量提供,它将按照您描述的方式工作。

假设这两个图像具有相同的标记方案(它们不一定需要)。您可以更新 Compose 文件来表示

version: '3.8'
services:
    nginx:
        restart: unless-stopped
        image: ghcr.io/user/frontend:${TAG:-latest} # <--
        ports:
            - 80:80
        depends_on: 
            - backend
    backend:
        restart: unless-stopped
        image: ghcr.io/user/backend:${TAG:-latest} # <--

请注意

$TAG
行末尾的
image:
参考。如果环境中未设置
TAG
,它将使用
latest
,但如果设置了,它将使用确切的构建。

现在,如果我跑步:

TAG=20221020 docker-compose up -d

对于这两个容器,Compose 会注意到它们正在运行较旧的版本,自动从 GitHub 中提取更新的映像,并根据较新的映像重新启动两个容器。

这给您的连续部署系统带来了轻微的复杂性,需要知道当前的映像标签。不过,作为交换,您可以非常轻松地回滚 - 如果今天的构建结果存在严重错误,您可以使用不同的标签运行完全相同的命令,以在昨天的构建上重新部署。如果您正在考虑迁移到 Kubernetes,这样的设置也是必要的,因为它取决于

image:
字符串的文本更改以触发重新部署。


0
投票

我为此创建了一个开源 CLI 工具,Pose:https://github.com/mrsarm/pose

变量替换是一个强大的工具,但当您的撰写文件中有多个图像是分布式应用程序的一部分(例如

"${TAG:-latest}"
),但只有少数图像是使用您想要使用的新
$TAG
发布时,变量替换就显得不足了只要有空,就继续使用
latest
。这正是姿势允许做的:从另一个文件动态构建一个新的撰写文件,用新的远程版本(如果存在)替换图像中的标签版本,否则保留已设置的文件。

compose.yaml
示例:

services:
  web:
    image: mrsarm/web
  e2e:
    image: mrsarm/e2e
  api:
    image: mrsarm/api

以上图片均默认使用“最新”。现在,假设有 3 个服务(还有 3 个镜像),我们只在 Docker 注册表中发布了其中 2 个带有“client-vat-field”标签的服务,并且我们想要创建一个新的

ci.yaml
文件,其中包含动态更改,检查 Docker 注册表中是否存在该标记。这是允许创建新的撰写文件的
pose
命令:

pose config --tag "client-vat-field" --progress -o ci.yaml

CLI 输出将如下所示:

DEBUG: manifest for image mrsarm/web:client-vat-field ... found
DEBUG: manifest for image mrsarm/e2e:client-vat-field ... not found
DEBUG: manifest for image mrsarm/api:client-vat-field ... found

现在新的

ci.yaml
文件是:

services:
  web:
    image: mrsarm/web:client-vat-field
  e2e:
    image: mrsarm/e2e
  api:
    image: mrsarm/api:client-vat-field

Pose 还有其他有用的命令来处理 compose 文件,例如以

.env
格式列出服务的所有环境变量,并且在项目文档中提供了如何将其与实际示例(CI 环境)集成的示例),例如在 Github Actions 上使用它。

为什么会这样?因为在发布之前在 CI 环境中对分布式应用程序进行端到端测试需要能够选择要使用的图像,而无需人工手动编辑撰写文件。有关此工作流程的更多信息在姿势文档中进行了解释:https://github.com/mrsarm/pose/blob/main/Run-CI-envs.md

© www.soinside.com 2019 - 2024. All rights reserved.