如何使用docker-compose多个图像标签

Dir*_*irk 11 tags docker docker-compose

根据这个这个 GitHub问题,目前在使用docker-compose构建一个或多个图像时,如何为服务的图像提供多个标签没有本地方式.

我的用例是构建docker-compose.yml文件中定义的图像,并使用一些自定义标记(例如某些构建编号或日期或类似标记)标记一次,并将其标记为latest.

虽然docker使用docker tag可以轻松实现这一点,但docker-compose只允许在图像键中设置一个标记.使用docker tag连同docker-compose是不是一种选择对我,因为我要保持我的所有码头工人有关的定义docker-compose.yml文件,而不是将其复制过来到我的构建脚本.

在首先使用docker-compose和不必硬编码/复制图像名称的情况下,设置多个标签会有什么好处?

Dir*_*irk 11

我提出了几个不同复杂程度的解决方法.它们都依赖于${IMAGE_TAG}存储代表例如构建号的自定义标记的假设.我们希望使用此标记以及标记所有服务的图像latest.

grepdocker-compose.yml文件中的图像名称

images=$(cat docker-compose.yml | grep 'image: ' | cut -d':' -f 2 | tr -d '"')
for image in $images
do
  docker tag "${image}":"${IMAGE_TAG}" "${image}":latest
done
Run Code Online (Sandbox Code Playgroud)

但是,如果某人添加了docker-compose.yml例如看起来像的评论,则这很容易出错# Purpose of this image: do something useful....

建两次

使用${IMAGE_TAG}在你的环境变量docker-compose.yml描述文件中的第一个例子在这里.

然后,只需运行构建过程两次,每次${IMAGE_TAG}使用不同的值替换:

IMAGE_TAG="${IMAGE_TAG}" docker-compose build
IMAGE_TAG=latest docker-compose build
Run Code Online (Sandbox Code Playgroud)

第二个构建过程应该比第一个构建过程快得多,因为所有图像层仍应从第一次运行中缓存.

这种方法的缺点是它会使每个单独服务的两个后续构建过程充斥您的日志输出,这可能会使搜索更难以查找有用的东西.

此外,如果你有任何命令Dockerfile总是刷新构建缓存(例如,ADD从具有自动更新last-modified头的远程位置获取命令,添加由外部进程不断更新的文件等),那么额外的构建可能会减慢速度显着下降.

docker-compose.yml使用一些内联Python代码从文件中解析图像名称

使用yamlPython中的真实解析器(或任何其他语言,例如Ruby或者perl系统上安装的任何语言)比第一次提到的grep方法更强大,因为它不会被评论或编写yml文件的奇怪但有效的方式混淆.

在Python中,这可能如下所示:

images=$(python3 <<-EOF # make sure below to indent with tabs, not spaces; or omit the "-" before "EOF" and use no indention at all
    import yaml
    content = yaml.load(open("docker-compose.build.yml"))
    services = content["services"].values()
    image_names = (service["image"].split(":")[0] for service in services)
    print("\n".join(image_names))
EOF
)

for image in ${images}
do
docker tag ${image}:${IMAGE_TAG} ${image}:latest
done
Run Code Online (Sandbox Code Playgroud)

这种方法的缺点是执行构建的机器必须安装Python3以及PyYAML库.如前所述,此模式可以类似地与Python2或任何其他安装的编程语言一起使用.

使用某些docker命令的组合获取图像名称

使用一些本机dockerdocker-compose命令(使用go-templates)的以下方法编写起来有点复杂,但也可以很好地工作.

# this should be set to something unique in order to avoid conflicts with other running docker-compose projects
compose_project_name=myproject.tagging

# create containers for all services without starting them
docker-compose --project-name "${compose_project_name}" up --no-start

# get image names without tags for all started containers
images=$(docker-compose --project-name "${compose_project_name}" images -q | xargs docker inspect --format='{{ index .RepoTags 0}}' | cut -d':' -f1)

# iterate over images and re-tag
for image in ${images}
do
    docker tag "${image}":"${IMAGE_TAG}" "${image}":latest
done

# clean-up created containers again
docker-compose --project-name "${compose_project_name}" down
Run Code Online (Sandbox Code Playgroud)

虽然这种方法没有任何外部依赖性并且比grep方法更安全,但是在大型设置上执行创建和删除容器可能需要几秒钟(尽管通常不是问题).

  • 您可以在第一个示例中运行`docker-compose config`,它将删除所有注释并仅保留配置语句.IE浏览器.`docker-compose config | grep'形象:'| awk -F':''{print"image"$ 2",标签"$ 3}"`为我做了. (5认同)

Rom*_*ain 11

正如@JordanDeyton 所建议的,extends不能再在 Compose 文件格式中使用,> 3并且版本中添加的扩展字段功能3.4可以替换它以实现相同的目标。这是一个例子。

version: "3.4"
# Define common behavior
x-ubi-httpd:
  &default-ubi-httpd
  build: ubi-httpd
  # Other settings can also be shared
  image: ubi-httpd:latest

# Define one service by wanted tag
services:
  # Use the extension as is
  ubi-httpd_latest:
    *default-ubi-httpd
  # Override the image tag
  ubi-httpd_major:
    << : *default-ubi-httpd
    image: ubi-httpd:1
  ubi-httpd_minor:
    << : *default-ubi-httpd
    image: ubi-httpd:1.0
  # Using an environment variable defined in a .env file for e.g.
  ubi-httpd_patch:
    << : *default-ubi-httpd
    image: "ubi-httpd:${UBI_HTTPD_PATCH}"
Run Code Online (Sandbox Code Playgroud)

现在可以使用所有定义的标签构建图像

version: "3.4"
# Define common behavior
x-ubi-httpd:
  &default-ubi-httpd
  build: ubi-httpd
  # Other settings can also be shared
  image: ubi-httpd:latest

# Define one service by wanted tag
services:
  # Use the extension as is
  ubi-httpd_latest:
    *default-ubi-httpd
  # Override the image tag
  ubi-httpd_major:
    << : *default-ubi-httpd
    image: ubi-httpd:1
  ubi-httpd_minor:
    << : *default-ubi-httpd
    image: ubi-httpd:1.0
  # Using an environment variable defined in a .env file for e.g.
  ubi-httpd_patch:
    << : *default-ubi-httpd
    image: "ubi-httpd:${UBI_HTTPD_PATCH}"
Run Code Online (Sandbox Code Playgroud)


mix*_*xja 9

您还可以采取以下方法:

# build is your actual build spec
build:
  image: myrepo/myimage
  build:
  ...
  ...
# these extend from build and just add new tags statically or from environment variables or 
version_tag:
  extends: build
  image: myrepo/myimage:v1.0
some_other_tag:
  extends: build
  image: myrepo/myimage:${SOME_OTHER_TAG}
Run Code Online (Sandbox Code Playgroud)

然后你可以运行docker-compose build并且docker-compose push你将构建并推送正确的标记图像集

  • 遗憾的是它仅适用于撰写文件版本<3 (3认同)
  • @whoan 3.4+ 文件格式有扩展字段支持。您可以使用它来执行相同的步骤,尽管 YAML 格式更加晦涩难懂。参考:https://docs.docker.com/compose/compose-file/#extension-fields (3认同)

dud*_*oco 9

现在有一个使用buildx Baker 的内置解决方案,在v.0.7.0中发布。此功能是根据我在https://github.com/docker/buildx/issues/396中的建议实现的。

Docker 是捆绑buildx安装的,但是,如果您在 Mac 上运行 Docker Desktop,则buildx在撰写本文时捆绑的版本较旧,您将需要安装buildxDocker 之外的正确版本。

将扩展字段添加x-bake到您的docker-compose.yaml

version: '3.9'

services:
  my-app:
    image: my-repo/my-image:latest
    build:
      context: .
      dockerfile: Dockerfile
      x-bake:
        tags:
        - my-repo/my-image:${MY_TAG_1}
        - my-repo/my-image:${MY_TAG_2}
        - my-repo/my-image:${MY_TAG_3}

        - my-other-repo/my-image:${MY_TAG_1}
        - my-other-repo/my-image:${MY_TAG_2}
        - my-other-repo/my-image:${MY_TAG_3}
Run Code Online (Sandbox Code Playgroud)

要构建并标记图像,请运行:

buildx bake --load
Run Code Online (Sandbox Code Playgroud)

要构建、标记图像并将其推送到存储库甚至多个存储库:

buildx bake --push
Run Code Online (Sandbox Code Playgroud)


Mao*_*dok 5

我有一些使用环境变量的简洁解决方案(默认变量值的bash语法,在我来说是,latest但是您可以使用任何东西),这是我的写法:

version: '3'
services:
  app:
    build: .
    image: myapp-name:${version:-latest}
Run Code Online (Sandbox Code Playgroud)

使用默认标记生成并推送(如果需要推送到注册表),请使用环境变量更改版本,然后再次生成并推送:

docker-compose build
docker-compose push
export version=0.0.1
docker-compose build
docker-compose push
Run Code Online (Sandbox Code Playgroud)

  • 只是弹出来更新 @CharlieReitzel 的文档链接:https://docs.docker.com/compose/compose-file/#interpolation (2认同)