当前位置: 首页 > 知识库问答 >
问题:

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

闻人和歌
2023-03-14

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

我的用例是构建docker compose中定义的图像。yml将其归档,并使用一些自定义标记(例如一些构建编号或日期或类似标记)对其进行一次标记,然后将其作为最新标记进行一次标记。

虽然这可以通过使用docker标签的纯docker轻松实现,但docker-compose只允许在映像键中设置一个标签。将docker tagdocker-compose一起使用对我来说不是一个选项,因为我想将所有与docker相关的定义保留在docker-compose.yml文件中,而不是将它们复制到我的构建脚本中。

使用docker compose(docker compose)设置多个标签,而不必先硬编码/复制图像名称,这将是一个体面的解决方案吗?

共有3个答案

巫马炫明
2023-03-14

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

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

然而,如果有人在docker compose中添加注释,则很容易出错。yml,例如,看起来像此图像的目的:做一些有用的事情

使用${IMAGE_TAG}作为docker-compose.yml文件中的环境变量,如第一个示例中所述。

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

IMAGE_TAG="${IMAGE_TAG}" docker-compose build
IMAGE_TAG=latest docker-compose build

第二个构建过程应该比第一个快得多,因为所有图像层都应该在第一次运行时缓存。

这种方法的缺点是它会为每个服务使用两个后续构建过程来淹没您的日志输出,这可能会使搜索有用的东西变得更加困难。

此外,如果您的Dockerfile中有任何命令总是刷新生成缓存(例如,从远程位置提取的自动更新上次修改的头的添加命令,添加由外部进程不断更新的文件等),那么额外的生成可能会显著减慢速度。

在Python中使用真正的yaml解析器(或任何其他语言,例如Rubyperl或安装在您系统上的任何语言)比第一个提到的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

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

下面的方法使用一些本机dockerdocker-compose命令(使用go模板)编写起来有点复杂,但也很好用。

# 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

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

璩和璧
2023-03-14

您还可以采取以下方法:

# 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}

然后,只需运行docker compose build和docker compose push,即可构建并推送正确的标记图像集

江棋
2023-03-14

我有一些使用环境变量的漂亮而干净的解决方案(默认变量值的bash语法,在我的情况下,它是最新的,但您可以使用任何东西),这是我的写作:

version: '3'
services:
  app:
    build: .
    image: myapp-name:${version:-latest}

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

docker-compose build
docker-compose push
export version=0.0.1
docker-compose build
docker-compose push
 类似资料:
  • 我想通过docker compose构建图像,并为其设置特定标记。文件说: Comment将构建并用生成的名称标记它,然后使用该映像。 但是我找不到指定标签的方法,对于构建的图像,我总是看到“最新”标签。

  • 问题内容: 我想通过docker-compose建立映像并为其设置特定标签。文档说: Compose将使用生成的名称来构建并标记它,然后使用该图像。 但是我找不到指定标签的方法,对于生成的图像,我总是看到“最新”标签。 问题答案: 似乎文档/工具已更新,您现在可以将标记添加到脚本中。这对我来说是成功的。 例: https://docs.docker.com/compose/compose- fil

  • 我目前正在使用https://medium.com/@sunnykay/docker-开发-工作流-节点-快递-蒙戈-4bb3b1f7eb1e尝试这个教程 第一部分在构建< code>docker-compose.yml的地方运行良好,在本地构建完全运行良好,因此我尝试标记它,并将其推入我的< code>dockerhub以了解和尝试更多内容。 这最初是文件中的内容,然后是教程 当我使用< cod

  • 我有多个微服务,我使用docker compose进行开发部署。当microservices代码库中有一些更改时,我会触发ci作业来重新部署它们。我有下面的脚本来做这件事。但每次我都必须从头开始构建所有图像,然后运行它们。完成所有这些操作后,我得到了图像。所以我使用最后一个脚本来删除它们。你有什么建议使这个过程更实用?是否有任何方法可以更新现有图像而不使用新的更改将其删除? 其他信息:我正在使用

  • 我必须将一个在几个容器中运行的应用程序交付给一个客户。我可以用 我的目标是交付一个只有docker-compose.yml和图像(app1.tar,app2.tar...)的zip文件夹需要运行集装箱。

  • 问题内容: 我想做这样的事情,我可以依次运行多个命令。 问题答案: 想通了,使用 。 例: 多行中的相同示例: 要么: