如何让 docker-compose 使用存储库中的最新图像

how to get docker-compose to use the latest image from repository

我不知道我做错了什么,但如果不先从系统中完全删除旧容器,我就无法docker-compose up使用我们注册表中的最新映像。尽管 docker-compose pull 已获取更新的图像,但看起来 compose 正在使用之前启动的图像。

我查看了 ,这似乎与我的问题相似,但那里提供的解决方案中有 none 对我有用,因为我正在寻找可以在生产服务器,我不想在再次启动它们之前删除所有容器(可能丢失数据?)。我只想让 compose 检测更改图像的新版本,拉取它们,然后使用这些新图像重新启动服务。

我为此创建了一个简单的测试项目,其中唯一的目标是让版本号在每个新版本中增加。如果我浏览到创建的 nginx 服务器(这在本地按预期工作),则会显示版本号。

docker版本:1.11.2 docker-撰写版本:1.7.1 OS:使用 docker-toolbox

在 CentOS 7 和 OS X 10.10 上测试

我的docker-compose.yml:

version: '2'
services:
  application:
    image: ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev
    volumes:
      - /var/www/html
    tty: true

  nginx:
    build: nginx
    ports:
      - "80:80"
    volumes_from:
      - application
    volumes:
      - ./logs/nginx/:/var/log/nginx
  php:
    container_name: buildchaintest_php_1
    build: php-fpm
    expose:
      - "9000"
    volumes_from:
      - application
    volumes:
      - ./logs/php-fpm/:/var/www/logs

在我们的 jenkins 服务器上,我 运行 构建和标记图像

cd $WORKSPACE && PROJECT_VERSION=$(cat VERSION)-dev
/usr/local/bin/docker-compose rm -f
/usr/local/bin/docker-compose build
docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest ourprivate.docker.reg:5000/ourcompany/buildchaintest:$PROJECT_VERSION
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest

这似乎是在做它应该做的事情,因为每次构建完成并且版本号被提升时,我都会在我们的存储库中获得一个新的版本标签。

如果我现在运行

docker-compose pull && docker-compose -f docker-compose.yml up -d

在我电脑上的一个文件夹中,其中的内容只有 docker-compose.yml 和构建 nginx 和 php 服务所需的 Dockerfiles,我得到的输出是不是在注册表中标记或显示在 docker-compose.yml (0.1.8) 中的最新版本号,而是之前的版本,即 0.1.7。但是 pull 命令的输出会提示获取了新版本的图像:

Pulling application (ourprivate.docker.reg:5000/ourcompany/buildchaintest:latest)...
latest: Pulling from ourcompany/buildchaintest
Digest: sha256:8f7a06203005ff932799fe89e7756cd21719cccb9099b7898af2399414bfe62a
Status: Downloaded newer image for docker.locotech.fi:5000/locotech/buildchaintest:0.1.8-dev

只有我 运行

docker-compose stop && docker-compose rm -f

然后是 运行 docker-compose up 命令,我可以让新版本按预期显示在屏幕上吗?

这是 docker-compose 的预期行为吗?也就是说,即使在生产服务器上,我是否应该总是在 运行 宁 up 之前再次执行 docker-compose rm -f ?或者我在这里做一些违背谷物的事情,这就是它不起作用的原因?

目标是让我们的构建过程构建和创建 docker-compose.yml 中所需图像的标记版本,将它们推送到我们的私有注册表,然后为 "release to production-step" 简单地将 docker-compose.yml 复制到生产服务器,并 运行 一个 docker-compose pull && docker-compose -f docker-compose.yml up -d 新图像开始生产。如果有人对此有提示或可以指出此类设置的最佳实践教程,我们也将不胜感激。

为了结束这个问题,似乎有效的确实是 运行ning

docker-compose stop
docker-compose rm -f
docker-compose -f docker-compose.yml up -d

即再次 运行ning up 之前移除容器。

这样做时需要记住的是,如果您只是 运行 rm -f,数据卷容器也会被删除。为了防止我明确指定要删除的每个容器:

docker-compose rm -f application nginx php

正如我在问题中所说,我不知道这是否是正确的过程。但这似乎适用于我们的用例,因此在我们找到更好的解决方案之前,我们将继续使用这个解决方案。

为了确保您使用的是注册表中的 :latest 标签的最新版本(例如 docker hub),您还需要再次提取最新标签。如果它发生变化,差异将在您再次 docker-compose up 时下载并启动。

所以这将是要走的路:

docker-compose stop
docker-compose rm -f
docker-compose pull   
docker-compose up -d

我将其粘贴到我 运行 开始 docker 合成的图像中并确保图像保持最新:https://hub.docker.com/r/stephanlindauer/docker-compose-updater/

我在我们的 7-8 docker 生产系统中看到过这种情况。 在生产中对我有用的另一个解决方案是 运行

docker-compose down
docker-compose up -d

这将删除容器,并且似乎 'up' 从最新图像创建新容器。

这还没有解决我对每个更改的容器进行向下+向上的梦想(连续地减少停机时间),但它可以强制 'up' 更新容器。

'up' 命令的 docker-compose 文档明确指出,如果自上次执行 'up' 以来图像发生更改,它会更新容器:

If there are existing containers for a service, and the service’s configuration or image was changed after the container’s creation, docker-compose up picks up the changes by stopping and recreating the containers (preserving mounted volumes).

因此,通过使用 'stop',然后是 'pull',然后是 'up',这应该可以避免 运行 容器的体积丢失问题,当然,容器除外其图片已更新。

我目前正在试验这个过程,很快就会在评论中包含我的结果。

要获取最新图像,请使用 docker-compose build --pull

我使用下面的命令,它真的是 3 合 1

docker-compose down && docker-compose build --pull && docker-compose up -d

此命令将停止服务,拉取最新映像,然后启动服务。

选项down解决这个问题

我运行我的撰写文件:

docker-compose -f docker/docker-compose.yml up -d

然后我用down --rmi all

删除所有

docker-compose -f docker/docker-compose.yml down --rmi all

Stops containers and removes containers, networks, volumes, and images
created by `up`.

By default, the only things removed are:

- Containers for services defined in the Compose file
- Networks defined in the `networks` section of the Compose file
- The default network, if one is used

Networks and volumes defined as `external` are never removed.

Usage: down [options]

Options:
    --rmi type          Remove images. Type must be one of:
                        'all': Remove all images used by any service.
                        'local': Remove only images that don't have a custom tag
                        set by the `image` field.
    -v, --volumes       Remove named volumes declared in the `volumes` section
                        of the Compose file and anonymous volumes
                        attached to containers.
    --remove-orphans    Remove containers for services not defined in the
                        Compose file

我正在使用以下命令获取最新图像

sudo docker-compose down -rmi all

sudo docker-compose up -d

这个问题我折腾了半天。原因是一定要检查音量是在哪里录制的。

volumes: - api-data:/src/patterns

但事实是,在这个地方是我们更改的代码。但是在更新docker时,代码并没有改变。

因此,如果您正在检查其他人的代码并且由于某种原因您没有更新,请检查此。

所以一般来说,这种方法是有效的:

docker-compose down

docker-compose build

docker-compose up -d

如果 docker 组合配置在文件中,只需 运行:

docker-compose -f appName.yml down && docker-compose -f appName.yml pull && docker-compose -f appName.yml up -d

但是

https://docs.docker.com/compose/reference/up/ -quiet-pull Pull without printing progress information

docker-compose up --quiet-pull

不工作?

[EDIT] DO NOT USE
The below is in the spec but, as pointed out in the comments, has not been implemented yet (docker-compose 1.29.2 and 2).

自 2020 年 5 月 7 日起,docker-compose 规范还为服务定义了“pull_policy”属性:

version: '3.7'

services:
  my-service:
    image: someimage/somewhere
    pull_policy: always

docker-compose spec 说:

pull_policy defines the decisions Compose implementations will make when it starts to pull images.

可能的值为(tl;dr,查看规范了解更多详情):

  • 总是:总是拉
  • 从不:不拉(如果找不到图像则中断)
  • 缺少:如果图像未缓存则拉取
  • 构建:始终构建或重建

即使我的容器是 运行,我也使用以下内容,它更新得很好。

docker-compose pull
docker-compose up -d
docker-compose pull
docker-compose up -d
docker image prune -af

对我有用。

先拉取最新的镜像, 比更新容器, 最后清理我们不需要的图像。

您的 docker-compose.yml 使用 image 来引用 ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev。这意味着 运行ning docker-compose build 不会对 ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev 采取任何行动。某处必须有如下命令运行:

docker build -t ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev

这会将版本控制的构建放入您的存储库中。但它不会更新其最新标签。这仍然指向先前的版本(例如,0.1.7-dev)。

然后,您 运行 在您的 jenkins 上执行其他命令:

cd $WORKSPACE && PROJECT_VERSION=$(cat VERSION)-dev
/usr/local/bin/docker-compose rm -f
/usr/local/bin/docker-compose build
docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest ourprivate.docker.reg:5000/ourcompany/buildchaintest:$PROJECT_VERSION
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest

作为 docker-compose build 的一部分,您实际上 运行正在 docker pull ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev 服务器上。但是,这并没有说明标签 ourprivate.docker.reg:5000/ourcompany/buildchaintest:latest(您在命令 docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest ourprivate.docker.reg:5000/ourcompany/buildchaintest:$PROJECT_VERSION 中引用的标签)是如何进入您的服务器的。如果 latest 标签事先没有被其他东西定义,那个 docker tag 命令会给出这个错误:No such image: ourprivate.docker.reg:5000/ourcompany/buildchaintest:latest。因此,在 运行 执行您显示的命令之前,您的詹金斯服务器必须 运行 类似于以下内容:

docker pull ourprivate.docker.reg:5000/ourcompany/buildchaintest

此命令会导致它提取存储库中当时设置为 latest 的任何内容。因为你没有提供证据证明你在 运行 上面的 docker pull 命令之前将你的新构建 buildchaintest:0.1.8-dev 推送为 buildchaintest:latest,我们必须假设这是旧的版本来自。因此,您的标记命令有效地执行了此操作:

docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest:latest ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev

其中,如果 latest0.1.7-dev 指向相同的东西,则与做的相同:

docker tag ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.7-dev ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev
docker push ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev

然后,稍后,当您 运行 docker-compose pull && docker-compose up -d 时,它当然会拉取存储库中设置为 ourprivate.docker.reg:5000/ourcompany/buildchaintest:0.1.8-dev 的内容,这应该是旧版本,因为您标记了 0.1。 7-dev 为 0.1.8-dev.

备注

您似乎假设 docker-compose build 做了一些与建筑 buildchaintest 相关的事情。然而,事实并非如此。您在 docker-compose.yml 中设置了 image 而不是 build。这意味着 docker-compose build 不会 构建 buildchaintest docker 图像——它只会直接拉取 运行 docker图片标签。由于 docker-compose build 不会尝试构建 buildchaintest,因此在调用该图像后尝试标记或推送该图像毫无意义。

此外,如果您同时指定 buildimagedocker-compose push 存在并且会执行所有标记和推送操作(因为 image 用于通知 docker-compose 它应该为构建的东西设置一个标签)。这将推送正确的标签(并且对于您的 docker-compose.yml 文件将正确地成为 no-op)。

你的 docker-composebuild 而没有 image。这些东西将在您 运行 docker-compose up 的任何地方建造。所以在构建服务器上 运行ning docker-compose build 中没有意义(除非你添加 image 来设置标签并保存那些构建的图像并使用 docker-compose push)(除了测试建造 运行 秒完成)。您不会在部署期间为自己节省任何时间或减少服务器执行的工作。您正在增加构建事物的次数以及系统中节点之间的可变性(因为构建服务器上构建的任何内容都将与 运行ning 不同(例如,文件时间戳、更新的图像标签)在你的服务器上。

很遗憾,您的问题不可信。您使用命令时,就好像它们具有与预期不同的行为。很抱歉攻击你的问题,但我了解到一些关于 docker tagdocker-compose 如何工作的令人惊讶的事情(对我来说)。谢谢!

tl;博士

确保您确实标记了正确的图像并将其推送到您的存储库中!

拉取新镜像:docker-compose pull

用新图像重建 docker 容器:docker-compose up --force-recreate --build -d

删除不用的图片:docker image prune -f