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

如何在docker compose中使用多个图像标记,docker,tags,docker-compose,Docker,Tags,Docker Compose,根据和GitHub的问题,目前还没有一种原生方法,在使用docker compose构建一个或多个映像时,如何为服务映像提供多个标记 我的使用案例是构建一个docker compose.yml文件中定义的图像,并用一些自定义标记(例如一些构建编号或日期或类似标记)对它们进行一次标记,然后将它们标记为最新的 虽然这可以通过使用纯docker轻松实现,但docker compose只允许在中设置一个标记。使用docker-tag和docker-compose对我来说不是一个选项,因为我想在docke

根据和GitHub的问题,目前还没有一种原生方法,在使用
docker compose
构建一个或多个映像时,如何为服务映像提供多个标记

我的使用案例是构建一个
docker compose.yml
文件中定义的图像,并用一些自定义标记(例如一些构建编号或日期或类似标记)对它们进行一次标记,然后将它们标记为
最新的

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


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

我提出了两种不同复杂性的解决方案。它们都基于这样的假设,即
${IMAGE\u TAG}
存储表示构建号的自定义标记,我们希望使用此标记以及
最新的
标记所有服务的图像

grep
来自
docker compose.yml
文件的图像名称 但是,如果有人在
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
中有任何命令总是刷新生成缓存(例如,一个
ADD
命令从远程位置获取,带有自动更新
last modified
头,添加由外部进程不断更新的文件等)然后,额外的构建可能会显著降低速度

使用一些内联Python代码解析docker compose.yml文件中的图像名称 在Python中使用真正的
yaml
解析器(或任何其他语言,如
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

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

您也可以采用以下方法:

# 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
,然后您将构建并推送正确的标记图像集

我有一些使用环境变量的漂亮而干净的解决方案(默认变量值的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

正如@JordanDeyton
所建议的那样,extends
不能再在Compose file format
>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}"

您可以在第一个示例中运行
docker compose config
,该示例将删除所有注释,只留下config语句。例如,
docker compose-config | grep'image:“| awk-F”:“{print”image“$2”,tag“$3}”
为我做。
docker compose image
输出
Container | Repository | tag | image Id | Size
,值如
project | foo | 1 | project | foo | latest | caffee098 | 1.1 GB
。(添加
|
是为了适应这种混乱的行布局。)也许这可以用来改进上一个示例,使
--项目名称不再需要。遗憾的是,它只适用于编写文件版本<3贪婪,
docker compose.yml
不再支持这种语法@Maoz Zadok有下面正确的方法。如果只是为了清楚起见,请使用您自己的环境变量,该变量不会与任何Docker关键字冲突(例如,
version
)。@whoan 3.4+文件格式中有扩展名字段支持。您可以使用它执行相同的步骤,尽管YAML格式比较模糊。参考:@JordanDeyton好主意,我已经根据你的建议发布了。谢谢我会为version环境变量使用不同的名称。但除此之外,这看起来很干净。这里描述了环境变量替换的细节:非常流畅,但我同意@charlietEitzel关于使用更好的变量名的观点,这可能是我们目前所能做的最好的了。不过,它确实建造了两次。我知道,我知道,缓存的图像第二次用于构建,但仍然如此。如果compose文件支持开箱即用的多个标记,那就更好了。对于那些阅读者,docker compose 1.17.0中添加了对文件格式版本3.4的支持。compose文件参考页包括一个格式矩阵和docker引擎版本,但我一直不清楚如何将Docker引擎版本映射到Docker compose版本
docker-compose build
docker-compose push
export version=0.0.1
docker-compose build
docker-compose push
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}"