从https://github.com/docker/compose/issues/4315可以看出, docker-compose
中存在的extends
功能尽管存在缺陷,但似乎很受用户欢迎。 但是,到目前为止,它还没有被添加到引擎对 Compose 格式的实现中。 到目前为止,我们已经建议用户在使用 v3 时简单地扁平化他们的 Compose 文件结构,但这是我们想要采用的长期解决方案吗? 我们如何为已经依赖此功能的用户提供清晰的升级路径?
抄送@dnephin @vdemeester
我已经添加了一些注释https://github.com/docker/compose/issues/4315#issuecomment -280617251 给我带回扩展,因为它存在直到 docker compose 文件 2.1 版本不是一个好主意,但我的主要功能错过是能够声明抽象服务(永远不应该运行,但为了方便起见,可以用来对服务的公共属性进行分组)。
同意 docker/compose#4315 的评论,即extends
工作方式有点简陋。
我不会推荐一个解决方案,但是 FWIW,为了显示滥用的程度,这里是装饰我们撰写文件顶部的约定:
#
# Docker Compose configuration
#
# Due to lack of "expressivity" in Compose, we define our own couple of service
# "pseudo-types":
#
# - image-only services (name: *-image)
#
# The only goal of these is to build images. No other services build images.
#
# These have entrypoint overridden to exit immediately.
#
# - base services (name: *-base)
#
# These contain common configuration and are intended to be extended.
#
# Their command (not entrypoint, to keep the original one) is overridden to
# exit immediately. Service must support a command to exit immediately.
#
# - task services (name: *-task)
#
# These are intended for running one-off commands.
#
# Their default command is overridden to exit immediately. Service must
# support a command to exit immediately.
#
# - "real" services
#
# These are actual services that stay up and running.
#
version: '2'
services:
...
我认为 v2.1 中的 extends 是一个不错的选择。 Extends 其实简单易懂,这对于每个环境来说都是一个很好的实践,在 dev、prod 和 env 之间进行一点可读的转换。
其实我有
这是有效的,我不明白为什么我们应该在这张票中搜索一个完整的重写,但更多的是保留一个有趣的功能。 对于其他技术无法轻松解决的特殊用例,扩展是一个很好的部分。 我对扩展的可能性感到满意。
也阻止我们升级到 v3.x 格式。
我们将 docker 容器定义保存在每个实例文件夹的布局中,其中每个文件夹都包含一个docker-compose.yml
,用于定义手头容器实例的 env 细节。 为了找出常见的东西 (DRY),我们在父文件夹中使用基本服务定义并使用extend
。
所以当我需要管理一个特定的容器实例时,我只需要将cd
放入正确的文件夹中,然后可以直接运行 docker-compose 命令而无需进一步配置(团队成员不需要-f
标志需要查找或知道,只需按预期开箱即用)。
我被禁止使用版本 3 撰写文件。
我使用services.yml
来定义我的服务的基本布局,然后使用dev.services.yml
为我的开发环境扩展它(主要是添加卷),但我喜欢扩展时的(干)可重用性添加。 这不是一个交易破坏者,但它会阻止我转向第 3 版,除非有必须具备的功能。
不过,我不反对用更合适的方法改进 v2.1 的“扩展”解决方案。 抽象服务之类的东西使用起来更安全,功能也更强大。
例如(因为它是抽象的)我可以想象支持抽象卷/挂载点/网络,其中抽象基本服务定义本地挂载点或服务所需的网络,而不定义主机部分 - 这意味着派生服务可以定义/将安装/卷和网络的主机部分映射到他的主机/阶段环境中的适当内容。
据我所知,这是我们现在不能用“扩展”来做的事情的一个例子,并且会打开一些有趣的可能性。
取消扩展功能根本没有帮助。 我们有很多 Web 服务以相同的卷映射、环境变量和标签集启动。 他们也有相同的健康检查政策。 更不用说端口了。 如果您在同一主机中处理多个项目,则使用多个 -f 选项组合撰写文件既乏味又容易出错。
@shin- 这会在 3.2 模式中恢复吗?
我真的,真的很想将extends
恢复为文件格式。 我一直在使用它来进一步完善一些项目的抽象服务。 我知道多个-f
选项几乎符合要求,但并不总是有效。 例如,我宁愿经常将抽象服务的名称更改为在手头项目的上下文中更有意义的名称。 这是多个-f
选项不支持的覆盖。
不过,我不介意丢失确切的extends
,只要它们是在文件中“实例化”抽象服务的其他方式。
我有一个带有通用服务文件和扩展它的一堆服务的设置,主要更改卷,所以我会说我依赖extends
功能并且看不到其他好方法来描述我的设置。
--frustrated
+1
我可以看到扁平化 docker-compose 文件的建议背后的逻辑,但我不喜欢在多个项目中复制定义我们的开发服务拓扑的代码的想法。 我们现在将使用 -f 解决方法,使用 shell 脚本,这样开发人员就不必记住在哪些情况下要包含哪些服务。
我希望可以在这里找到一个令人满意的解决方案,以便更好地分解组合结构!
在我的用例列表的顶部是 DRYup 我的配置管理的服务囤积。 我想我可以利用 v3.x 的“扩展”。 我不想回到 v2 ......而且我不想遇到必须使用 -f 进程变通方法的特殊情况。
嘿,有人开始研究这个吗? 我找不到 PR 来跟踪。 它也会为我们在这里简化很多事情(用例与上面描述的非常相似)。
由于版本 3 已冻结并且我需要一种共享通用配置的方法,因此我破解了一个小的解决方法,我想我可以在这里分享(我不确定这是否是正确的地方,但请随时告诉我我还能在哪里分享此信息:))
我不打算在这里详细说明,因为 repo 中有一个自述文件。
祝大家玩得开心☮️
+1
+1
+1
感谢您的 +1 💃
与此同时,我发现了另一个 docker noop image ,它小了 10^3 倍(由于实际的 noop 是用汇编编写的)。
不幸的是,该存储库中没有许可证。 我已经在facebk上给业主写了一条消息,但他还没有回复。 如果更多人向他询问,他可能会添加许可证:)
可能有助于某些扩展用例(单个文件中的用例)的东西是对 YAML 锚点的支持: https :
看来 JSON Schema 可能无法对它们service must be a mapping, not a NoneType.
进行验证。
嘿, @grayside ,yaml 锚确实有效,至少对我而言。 请参阅我上面的评论以了解我如何使用它们。
好的,但是使用一些 noop 服务太难过了不是吗?
特别是对于 env vars,这些 env vars 处理什么样的值? 如果是关于秘密的,请使用群秘密功能(或任何其他秘密解决方案)。 如果是关于设置,我们认为大部分时间设置都是特定于应用程序/服务的,而不是在服务之间共享的。
如果您需要在服务之间共享设置,大多数情况下是在您启动相同的容器映像但用于不同的运行时目的/任务(消费者、生产者、http 工作者等)时。
如果是关于设置,我们认为大部分时间设置都是特定于应用程序/服务的,而不是在服务之间共享的。
我倾向于不同意。 在我目前正在进行的项目中,我将它用于例如卷:
# Volume paths
environment:
- &volume_a volume-a:/usr/share/my_project/volumes/volume-a
- &volume_b volume-b:/usr/share/my_project/volumes/volume-b
- &volume_c volume-c:/usr/share/my_project/volumes/volume-c
- &volume_d volume-d:/usr/share/my_project/volumes/volume-d
现在我可以像这样指定这些卷:
volumes:
- volume-a:
- volume-b:
- volume-c:
- volume-d:
services:
some-service:
image: some-image
volumes:
- *volume_a
- *volume_b
some-other-service:
image: some-other-image
volumes:
- *volume_b
- *volume_c
some-third-service:
image: yet-another-image
volumes:
- *volume_a
- *volume_b
- *volume_c
- *volume_d
这使得导航不同的卷变得更容易,而无需考虑您在哪个容器中。恕我直言,这是使您的 docker-compose 设置更加一致、更易于使用和维护的一种方法。
好的,我明白@JanNash,但在下面的示例中,您没有任何 noop 服务,对吗?
但是对于很多情况,anchor 是不够的。
我的案例涉及为同一个项目支持多个环境。 您可以在此处查看我们项目的脚手架。
开发时使用devel.yaml
,但在生产中使用prod.yaml
。 还有test.yaml
。 它们都继承自common.yaml
并从.env
文件中获取一些公共变量。
每一种都有自己的特点:
这种简单的分离允许拥有一个非常敏捷和灵活的 DevOps 管道,每个人在不同的阶段使用相同的代码,只需根据使用的环境稍作调整。
我试图移动到撰写文件格式 v3,但不仅 在决定 Swarm 和 DRY 时,我们暂时选择了 DRY,但总有一天我们会需要 Swarm,我希望那一天能再次支持这两个功能...... ☺️extends
不支持,而且.env
,所以现在这将是一个维护噩梦(更多是因为缺少.env
,老实说)。
...或者至少我们有一种方法可以从 DRY-ful 解决方案中生成有效的 DRY-less 格式。 我认为docker-compose bundle
是为了那个,但现在似乎注定要弃用......
...或者我们有一个不同的工具来制作一切(我也在关注ansible-container )。 但这肯定不是“修复”。
https://github.com/moby/moby/issues/31101#issuecomment -301212524 中的链接包含带有 YAML 锚点工作示例的自述文件。 今天看了一下,再试一次,效果很好。 不知道我在做什么不同。
@ JanNash👍
@Yajo我听到你说的,这是一种解决方法,如果有一个由 docker/moby/docker-compose 提供的好的内置 DRY 解决方案,它会更好一个数量级(无论是正确的参考) . 让我们都希望很快就会到来,因为除此之外,我对 docker compose 很满意👍
~为了缺少 .env 支持,我还破解了一个解决方法(我的项目尚未投入生产,所以我的演讲有点廉价,我知道 :))。 为了在不同的环境中支持不同的环境变量集(例如依赖和图像版本/标签)(对我来说,现在是本地开发和一个小型开发服务器),我使用了两个文件, local.env
和development.env
,而不是仅通过docker-compose <command>
运行我的命令,我要么将相应的 .env 文件输入到我的 shell 中,要么像这样运行它: (. local.env && docker-compose <command>)
。 仍然是一个黑客,但就目前而言,我对此很满意。~
祝大家玩得开心🚶
甚至可能是两个数量级 :D
@JanNash等等! .env
不再支持3
吗?
我实际上不知道,我只是在评论中看到它不是。
我一直在使用 local.env 和 development.env 程序,主要是因为我在实现它时不知道 autoenv :D
很抱歉可能造成混淆。
啊, @ Yajo 在此评论中提到缺少 .env 支持。
你能详细说明一下吗,@Yajo?
哦对不起,我的错。 并不是它不起作用,只是您必须用env_file: .env
指定它,而不是像以前那样自动检测。 让我们回到最初的问题。
是否讨论将extends
丢弃在任何地方? 我很乐意在给出我们的用例之前通读它,因为我认为它是一个非常常用的功能,这很容易理解。
你好,我有一个问题——什么时候? “扩展”支持何时会在 v3 中恢复?
@JanNash你可以得到比那个小得多的方式。 我刚刚在 github 中针对你的 repo 提交了一个问题,我的机器上的 noop 从 750k 减少到 1200 字节。
我看到我现在不能在 swarm 中使用扩展。
任何想法如何使用相同的发布端口启动相同的服务,并在具有 1 个额外环境变量的服务上使用一个容器?
+1 用于扩展对 swarm 堆栈部署的支持
你好,
我们正在运行一个微服务应用程序,该应用程序分布在多个 git 存储库中(每个存储库都有其 docker-compose 文件)。
部署由一个扩展每个服务的“根”docker-compose 文件引导:对我们来说,堆栈部署确实需要这个extends
特性。
因此,+1 还可以扩展对 swarm 堆栈部署的支持
谢谢。
您可以使用 YAML 简单继承(请参阅&default
、 <<: *default
)作为临时解决方案:
version: '3'
services:
worker: &default
build: .
command: bundle exec rake jobs:work
env_file:
- .env
volumes:
- .:/app
depends_on:
- db
- redis
links:
- db:postgres
web:
<<: *default
command: bundle exec puma -C config/puma.rb -p 3000
ports:
- "3000:3000"
spring:
<<: *default
command: bundle exec spring server
当然, extends
功能更好
当你扩展一个不同的文件时怎么样?
Yaml 没有文件扩展功能:(
Docker 的贡献者是否对此功能有任何更新? 是否计划重新引入? 如果没有,是否有类似的计划? 如果没有,为什么不..?
@quolpr ,恐怕您的“YAML 简单继承”代码在大多数情况下不会替换extends
,因为“原型”(即&default
)将始终被 Docker Compose 解释为名为worker
。 因此,哪些服务 a) 需要明确定义,b) 可能是不需要的。
无论如何,绝对是一个有趣的功能。
@laugimethods您还可以使用 YAML 引用:
version: '3'
services:
spring:
build: ./app
command: /bin/sh -c "bundle exec spring server"
volumes: &default_volumes
- ./app:/app:delegated
- bundle:/bundle:nocopy
worker:
build: ./app
command: bundle exec sidekiq -v -C config/sidekiq.yml
volumes: *default_volumes
(注意&default_volumes
和*default_volumes
)
但我真的不明白为什么extends
功能被删除了🤔
仅供参考,为了替换缺少的“扩展”功能,我现在正在使用.yaml
文件的组合/合并:
https://github.com/Logimethods/smart-meter/blob/master/README.md#docker -compose
extends作品,简单而成熟,我认为如果有人将扩展视为某种反模式,那么就不要使用它,但请不要将其切断
我可以在不使用extends
情况下要求明确解释预期的方法吗? 我广泛使用它,特别是从 Git 子模块中包含的文件继承时,允许定义处理跨应用程序网络布线等的元项目。虽然我很清楚我可以指定多个docker-compose.yml
文件和让它们被覆盖,这是否意味着我需要在命令行中指定互连,而不是能够使用extends
将它们检入源代码控制? 还是我错过了 v3 中某个地方的一些新功能?
我在多个项目中大量使用extends
来为不同的环境和不同的主机继承一组通用的服务属性(阅读:我使用extends
从不同的文件继承)。
在昏迷中阅读extends
关键字的删除并试图找到不需要菊花链-f
docker compose 文件的替代品后,我很好奇删除extends
的原因是什么
我理解links
和volume-from
但只是避免在基本 yml 文件中使用它们似乎是最好的做法。
不可能仅仅因为它_可能_习惯将汽车颠倒而卸下汽车的车轮......对吗?
PS:noop 和 anchors 看起来很有趣,但它为最简单的项目增加了不必要的复杂性......
作为一个非常非常简单的例子:
common/common.yml
services:
web:
image: alpine:3.6
build: .
environment:
DOMAIN:
PREFIX:
dev/docker-compose.yml
services:
web:
extends: ../common/common.yml
service: web
ports:
- "8080:8080"
prod/docker-compose.yml
services:
web:
extends: ../common/common.yml
service: web
image: the-prod-image:latest-release
ports:
- "80:80"
- "80:443"
environment:
NEW_RELIC_KEY:
你是如何在没有extends
情况下保持 DRY 原则的?
目前我认为没有理由因此而从 2.1 版升级。
@teodorescuserban ,
菊花链 -f docker 撰写文件
这有什么问题? 您可以使用短别名创建自己的脚本来调用 docker-compose。
使用以下结构:
services:
web:
image: alpine:3.6
build: .
environment:
DOMAIN:
PREFIX:
services:
web:
ports:
- "8080:8080"
services:
web:
image: the-prod-image:latest-release
ports:
- "80:80"
- "80:443"
environment:
NEW_RELIC_KEY:
docker-compose -f common/common.yml -f dev/docker-compose.yml -p myproject up --build
docker-compose -f common/common.yml -f prod/docker-compose.yml -p myproject up --build
我不知道这个功能。 虽然它使您的 CLI 成为一个 💩,但它可以工作。
我认为,如果这将成为extends
的官方替代品,那么应该有一种方法可以让它变得更容易。
例如:
docker-compose.yml
version: "3" # or whatever
extend:
- ./common/common.yml
- ./dev/docker-compose.yml
services: # Not required now
# etc.
通过这种方式,您可以指向一个docker-compose.yml
文件,它可以满足您的所有需求。
一个有用的替代方法是在COMPOSE_FILE
env var 中支持多个撰写文件。
@Yajo
一个有用的替代方法是在 COMPOSE_FILE 环境变量中支持多个撰写文件。
从https://docs.docker.com/compose/reference/envvars/#compose_file :
此变量支持由路径分隔符分隔的多个 Compose 文件(在 Linux 和 macOS 上,路径分隔符为
:
,在 Windows 上为;
)。 例如:COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml
。 也可以使用COMPOSE_PATH_SEPARATOR
自定义路径分隔符。
@dermeister0您还可以使用https://github.com/ImmobilienScout24/yamlreader 等工具永久合并这些文件:
> yamlreader common/common.yml prod/docker-compose.yml > docker-compose-prod.yml
> docker-compose -f docker-compose-prod.yml -p myproject up --build
> cat docker-compose-prod.yml
services:
web:
build: .
environment:
DOMAIN: null
NEW_RELIC_KEY: null
PREFIX: null
image: the-prod-image:latest-release
ports:
- 80:80
- 80:443
@dermeister0很遗憾,感谢您的建议,这是一种笨拙的方法。 使用extends
消除了实际知道如何以菊花链方式连接它们的需要。 虽然我可以忍受自己这样做,但我永远无法将此解决方案应用于我亲爱的开发人员。
但是,我不知道COMPOSE_FILE
env 变量可以包含多个值。 谢谢@gsong ! 这很棒并且可以使用它(我在.env
文件中定义了它)。 这里有一个问题:在基本/通用文件中,我可能还有一些我不需要的服务。
以定义数据库和 Web 容器的平面公共文件为例。 在登台时,您希望它们都聚集在一起,但在生产时,您需要单独的主机用于 db 和用于 Web。
此外,默认情况下会加载 docker-compose.override.yml。
https://docs.docker.com/compose/extends/#understanding -multiple-compose-files
我在 3.3 版中使用这种方法:
docker-compose.yml
;docker-compose.override.yml
用于特定的开发配置和服务(例如 xdebug);docker-compose.staging.yml
用于特定的暂存配置选项。注意:我不在生产中运行 Docker。
使用这种方法,我可以使用docker-compose build
轻松地在本地构建,当我在登台上部署时,我使用:
docker-compose -f docker-compose.staging.yml -f docker-compose.yml build
我正在使用 Apache,并且我没有用于开发和登台的单独虚拟主机文件。 我花了很多时间来避免使用不同的文件。 最后,我看到唯一有效的方法是使用<IfDefine>
和环境变量(我在 yml 文件的环境部分设置),例如包含 ssl 配置。 我使用 TLD 和域前缀,所以我可以有类似www.example.local http://www.example.local/ :8080 和www.staging.example.com http://www.staging.example.com / . 在本地,网站在 http 下运行,并在 https 上登台。 使用这种方法,我不必维护不同版本的文件。 我认为在生产中也可以这样做,但正如我所说,我更喜欢避免在生产中使用 Docker,atm。
路径都是亲戚,所以容器可以在任何环境中工作。
我的 2 美分
-菲利波
就我而言,以前我使用过这样的东西:
感谢https://github.com/moby/moby/issues/31101#issuecomment -329482917 和https://github.com/moby/moby/issues/31101#issuecomment -329512231,我不知道,现在我可以使用不同的模式移动到 v3:
我还可以使用 env 变量进行任何需要的修改,因此在我的情况下,问题已解决。 谢谢! 🎉(对不起,我应该在抱怨之前正确阅读新文档)。
PS:仍然, extends
将是一件好事,但至少我们有一个足够公平的选择。 😊
@shin- 首先,我很失望地看到3.0
缺少extends
功能,但是 YAML 锚点(例如:https://github.com/JanNash/docker-noop)将是一个绰绰有余的更换。
唯一的问题是,就像上面的例子一样,你需要把你的锚点放在docker-compose.yml
文件的某个有效部分。
我们能否像 GitLab 一样获得(顶级) templates
属性或隐藏键,以便在定义锚点的方式上更加灵活?
@schmunk42看看https://github.com/docker/cli/pull/452
依赖 docker-compose.override.yml 的问题在于,它假定您只需要包含一种类型的覆盖和一层覆盖。
就我而言,我希望具有所有本地开发通用的某些行为,但如果开发人员运行的是 Windows、OSX 或 Linux,则可能需要它们略有不同。 为了在 docker-compose v3 上下文中保持这种可管理性,我让 Linux 用户在与登台环境相同的行为上进行操作,这可行,但意味着他们与其他开发人员略有不同。
我避免将-f
用于本地开发,因为我发现它很容易出现人为错误,并且依赖它作为太多事情的切换会导致麻烦。 选择一个文件似乎是合理的,选择多个是我小心避免强加的事情。
仅供参考,我认为一旦使用上面提到的x-
进行 hack,并且还使用.env
项目文件中的COMPOSE_FILE
变量菊花链 docker-compose 文件,添加 docker- compose.override.yml 应该可以解决我目前遇到的每个用例。
yml 锚也是我打算在不久的将来使用的一个很好的东西。
对x-
hack 美人不太满意,但我可以忍受。
谢谢你们的投入!
似乎extends
的删除引起了很多心痛,并且要么阻止迁移到 v3,要么求助于黑客。 我喜欢定义一个“模板”(或抽象)服务的能力,它可以承载一些常见的东西(例如更新策略)
我正在开发一个简单的 golang 过滤器实用程序,它可以使用extends
预处理 docker compose 文件并吐出一个干净的 v3 文件,扩展解析:
解析组合
(或 docker-compose up)
这至少适用于您的某些用例/为什么会遇到问题?
@pnickolov那对我来说
我一直在寻找ansible-container (我个人使用 ansible,但还没有在工作中使用),看起来它可以完成我需要的一切,但是像你这样的脚本会更可取(减少流失)
只要它可以递归处理extends:
键,我就会很高兴!
好的,看起来我们找到了extends
替代品......👍
令人不安的是,Moby 的项目管理似乎并未将保持兼容性视为关键要素。 向前兼容性对于更广泛的采用至关重要,尤其是对于部署到生产中的大型应用程序。 在不能保证像extends
这样的核心功能会保留的情况下,我们如何推动 Docker Swarm / Docker EE? 👎
好名声得来不易,失去容易……
就我个人而言,我更愿意依靠本机 YAML 功能来完成由extends
以v2
语法处理的任务,而不是自定义脚本或更大的解决方案,如 ansible。 我早些时候遇到了类似的问题,并在有使用多个 .yml 文件等解决方案之前开始编写自己的转换器。(https://github.com/schmunk42/yii2-yaml-converter-command) - 但它不是一个可行的解决方案。
对我来说,弃用功能也很好,如果这与版本控制策略一起完成; 你不能永远携带旧东西,即使这意味着我们需要做一些工作。
@schmunk42弃用功能很好,但仅限于:
不幸的是,这些要求(在我的书中)都不适用于extends
的弃用......
@laugimethods您需要使用v3
什么?
@schmunk42因为 Swarm:
3.x 版本,最新的推荐版本,旨在交叉兼容 Compose 和 Docker Engine 的 swarm 模式。 这是使用版本:'3' 或版本:'3.1' 等指定的,位于 YAML 的根目录中。
docker stack deploy 命令支持任何版本“3.0”或以上的 Compose 文件
顺便说一句,我的评论不仅与extends
,而且与未来可能发生的任何(痛苦的)弃用有关......
是的,由于群体模式,我们面临着同样的问题。
我首先问自己,为什么 docker CLI 现在能够使用--composer-file
输入。 但是从我们对docker/swarm
学习来看,在(自我管理的)swarm 上运行堆栈看起来是一件非常复杂的事情,并且有几个很好的理由将其转移到引擎中。
只是要注意我在这里的一些发现......从v2
过渡到v3.4
远非易事。
我的一些问题:
volumes_from
,很容易规避,因为无论如何我们都想删除它.env
文件(如docker-compose
)对 Docker CLI 没有影响docker stack deploy -c docker-compose.yml -c docker-compose.override.yml doro
)似乎无法正常工作,没有错误,但在我看来它们也没有正确合并 - 但也没有像docker-compose config
这样的命令来检查它docker-compose
没有“易于安装”(预发布)的二进制文件,它支持v3.4
语法; 像 Docker 边缘--scope swarm
创建外部网络抄送:@handcode
使用最新版本
我现在使用这个配置管道来代替我对 _extend_ 和 _noop_ 的使用
保持干燥一点
希望这有助于某人
base.yml (共享定义,这是一个有效的 yaml 文档,因此可以使用 _docker-compose config_ 合并)
version: '3.4'
networks:
net_back:
external: true
base-inject.yml (共享锚定义,不幸的是不能添加到base.yml因为锚不能在不同的 yaml 文件中引用,而是将它们作为文本注入foo.yml ,不是一个理想的方式来做到这一点)
x-logging: &logging
driver: json-file
options:
max-size: "50m"
max-file: "2"
foo.yml (通用堆栈定义,引用base.yml 中的对象, base-inject.yml 中的锚点和foo-dev.yml 中覆盖的对象)
version: '3.4'
[[base-inject]]
services:
foo:
image: ${DOCKER_REGISTRY}/foo:${IMAGE_VERSION}
volumes:
- type: volume
source: "volfoo"
target: "/foo"
networks:
- net_back
logging:
<<: *logging
foo-dev.yml (每个环境堆栈定义)
version: '3.4'
services:
foo:
ports:
- "8080:80"
volumes:
volfoo:
name: '{{index .Service.Labels "com.docker.stack.namespace"}}_volfoo_{{.Task.Slot}}'
driver: local
然后部署命令:
docker stack rm stack_foo && echo "waiting..." && sleep 3 &&
cat foo.yml | sed -e '/base-inject/ {' -e 'r base-inject.yml' -e 'd' -e '}' > ./foo-temp1.yml &&
export $(sed '/^#/d' ./dev.env | xargs) &&
docker-compose -f base.yml -f ./foo-temp1.yml -f foo-dev.yml config > ./foo-temp2.yml
docker stack deploy --with-registry-auth --prune --compose-file ./foo-temp2.yml stack_foo
这真是令人困惑!
阅读最新 docker 版本 ( v17.09
) 的文档以及v17.06
版本文档,此功能应该可用。
$ head -n1 docker-compose.yml
version: '3'
但是compose up
收益
ERROR: The Compose file './docker-compose.yml' is invalid because:
Unsupported config option for services.admin_application: 'extends'
使用extends
关键字时。
另外,我在compose
更改日志中找不到关于extends
删除的任何信息。
现在是哪个?!
像这样的关键信息不应该很难找到或隐藏在一些晦涩的 github 问题中。
$ docker --version
Docker version 17.09.0-ce, build afdb6d4
$ docker-compose --version
docker-compose version 1.16.1, build 6d1ac21
@jottr ,请参阅文档:
extends 关键字在 Compose 文件版本 2.1 之前的早期 Compose 文件格式中受支持(请参阅在 v1 中扩展和在 v2 中扩展),但在 Compose 版本 3.x 中不受支持。
所以如果你想使用extends
你需要坚持使用version: '2.1'
。
我的错。 它应该仍然位于文档的顶部,并带有一个红色的弃用警告标志。
我的错。 它应该仍然位于文档的顶部,并带有一个红色的弃用警告标志。
@jottr只需使用 Github 为其创建一个单独的问题,甚至为此创建一个 PR。 刚刚创建了问题 hiere: https :
在我的情况下,我有docker-compose-override.yml
如下:
yaml
version: "3.4"
services:
common:
extra_hosts:
- "host1:172.28.5.1"
- "host2172.28.5.2"
- "host3:172.28.5.3"
networks:
default:
external:
name: "common-network"
我还有其他几个docker-compose.yml
文件需要共享网络和 extra_hosts。 如何使用没有扩展功能来做到这一点?
yaml
version: "3.4"
services:
mongo:
image: "mongo"
container_name: "mongo"
hostname: "mongo"
volumes:
- "/opt/docker/mongo/default.conf:/usr/local/etc/mongo/mongod.conf"
- /opt/data/mongo:/data/db"
ports:
- "27017:27017"
command: "mongod --config /usr/local/etc/mongo/mongod.conf"
networks:
default:
ipv4_address: "172.28.5.4"
如果 docker-compose 支持 yaml 锚点和不同文件之间的引用,那就太好了。 也许,在合并文件后应用锚点和引用。
例如:
yaml
version: "3.4"
services:
common: &common
extra_hosts:
...
networks:
...
yaml
version: "3.4"
services:
mongo:
<<: *common
image: "mongo"
container_name: "mongo"
...
结果应该是:
yaml
version: "3.4"
services:
mongo:
image: "mongo"
container_name: "mongo"
extra_hosts:
// EXTRA HOSTS HERE
networks:
...
@sandro-csimas 这可以通过: https: //docs.docker.com/compose/compose-file/#extension -fields
@shin- 可以关闭这张票吗?
@rdxmb我不这么认为。 据我所知,你不能从另一个 docker-compose 文件扩展
我认为这是https://github.com/docker/compose/issues的问题是否正确?
一些调试:
# cat docker-compose.yml
version: "3.4"
services:
foo-not-bar:
<< : *common
foo-bar:
<< : *common
environment:
- FOO=BAR
x-common-definitions-for-all-our-services:
&common
image: phusion/baseimage
environment:
- FOO=NOTBARBYDEFAULT
这是与docker stack deploy -c docker-compose.yml test
使用 docker-compose 时:
# docker-compose up
ERROR: yaml.composer.ComposerError: found undefined alias 'common'
in "./docker-compose.yml", line 4, column 10
将 yml 文件更改为:
version: "3.4"
x-common-definitions-for-all-our-services:
&common
image: phusion/baseimage
environment:
- FOO=NOTBARBYDEFAULT
services:
foo-not-bar:
<< : *common
foo-bar:
<< : *common
environment:
- FOO=BAR
也适用于 docker-compose。
所以认为这也应该适用于多个文件,但事实并非如此:
# docker-compose -f compose-services.yml -f compose-default.yml config > docker-compose.yml
ERROR: yaml.composer.ComposerError: found undefined alias 'common'
in "./compose-services.yml", line 5, column 10
t# docker-compose -f compose-default.yml -f compose-services.yml config > docker-compose.yml
ERROR: yaml.composer.ComposerError: found undefined alias 'common'
in "./compose-services.yml", line 5, column 10
# cat compose-services.yml
version: "3.4"
services:
foo-not-bar:
<< : *common
foo-bar:
<< : *common
environment:
- FOO=BAR
# cat compose-default.yml
x-common-definitions-for-all-our-services:
&common
image: phusion/baseimage
environment:
- FOO=NOTBARBYDEFAULT
然而,当然,通过简单地使用cat
合并它是可能的:
# cat compose-default.yml compose-services.yml > docker-compose.yml && docker-compose up -d
WARNING: The Docker Engine you're using is running in swarm mode.
Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.
To deploy your application across the swarm, use `docker stack deploy`.
Creating network "test_default" with the default driver
Creating test_foo-bar_1 ...
Creating test_foo-not-bar_1 ...
Creating test_foo-bar_1
Creating test_foo-bar_1 ... done
使用以下版本在 xenial 上运行:
# docker --version
Docker version 17.11.0-ce, build 1caf76c
# docker-compose --version
docker-compose version 1.17.0, build ac53b73
@rdxmb ,谢谢!
所以我应该使用“cat”命令合并撰写文件并执行最终文件。
我也使用docker-compose config
来做到这一点。 环境特定设置的示例:
这是由 CI 管道运行的: docker-compose -f docker-compose.yml -f docker-compose.override.prod.yml config > docker-compose.prod.yml
然后我使用docker stack deploy -c .\docker-compose.prod.yml my-stack
为此投票,扩展对 v3 非常有用。
在 v2 中经常使用它,确实非常有用!
+1
我很想在 v3 中看到extends
支持。 它会帮助我清理我的docker-compose.yml
文件很多。
自从这个问题被提出以来已经快一年了,很明显有很多人需要这个功能。 然而,我根本没有读到 Docker 开发人员对此请求的回应,也没有解释为什么在发布之前它没有包含在 docker-compose v3 中。
如果我们甚至无法为相信新技术的客户沟通或维护功能,那么软件的可悲状态。
对这种情况的一种可能的解释(也可能是当前线程的摘要)是这样的:
cat
和高级方法。 简单的方法注释显示了 docker-compose 在最后加载多个文件的问题(是否有人为此创建了问题?)。 如果在 docker-compose 中修复了该问题,您甚至根本不需要合并文件。 所以对我来说,希望多文件支持的人应该按照@rdxmb 的建议在/compose/issues中继续。extends
(请参阅GitHub 项目事件,Docker 团队在这里提供了很好的透明度,谢谢!)并且您可能会将结果解释为“有很多其他东西对他们来说在战略上更重要”,但您可以我猜仍然为extends
写一个拉取请求。对我来说,这是一个完全可以理解的观点。
@aCandidMind同意。
恕我直言,尽管@aCandidMind提到的方法有效,但它们为extends
提供的更简单和更清晰的机制增加了复杂性。
也许是我,但是将适度复杂的扩展配置移动到扩展字段变得更加难以阅读和维护。
在阅读了许多评论和帖子后,我仍然不清楚为什么扩展被删除以及这种能力回归的优势是什么。
使用一点点 bash 魔法是可能的,我提出了一个测试回购,这样你就可以自己尝试了。
只需像这样构建您的stack deploy
命令:
docker stack deploy --compose-file=<(docker-compose -f docker/prod.yml -f docker/dev.yml config) <stackname>
@tylerbuchea - 这种 bash 魔法的唯一缺点是你可能会得到一个WARNING: Some services (<service-name(s)>) use the '<key>' key, which will be ignored. Compose does not support '<key>' configuration
。 这可能会引起一些混乱。 但是,嘿,它有效👍
@dnmgns你说得对! 感谢您指出了这一点。 就像@joaocc所说的,没有什么比原生支持
@tylerbuchea一种肮脏的方法是将 stderr 重定向到 /dev/null :)
docker stack deploy --compose-file=<(docker-compose -f docker/prod.yml -f docker/dev.yml config 2> /dev/null) <stackname>
一点都不丢人😄
我认为文档应该更明确地说明extend
周围的这种混淆。
extend
将用户重定向到 how-to-upgrade 文档,how-to-upgrade 文档指向extend
的描述extend
的决定背后有一个明确的想法。
看:
https://docs.docker.com/compose/extends/#extending -services
https://docs.docker.com/compose/compose-file/compose-versioning/#upgrading
关于@tylerbuchea伟大的基于单行 bash 的解决方案,
遗憾的是,它不支持某些高级 Docker 堆栈功能:
WARNING: Some services (web) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm.
WARNING: Some services (web) use the 'configs' key, which will be ignored. Compose does not support 'configs' configuration - use `docker stack deploy` to deploy to a swarm.
不是因为https://github.com/docker/cli/pull/569合并,从 18.03 开始, docker stack deploy
将支持将多个撰写文件合并为一个。 它没有完全替换 composefile 格式 v2 中的extends
键,但希望它涵盖更多用例👼
我自己的解决方法是使用yq
(如果使用 Bash,可以组合成一行):
yq merge --overwrite docker-stack.yml docker-stack.preprod.yml > merged-docker-stack.yml
docker stack deploy -c merged-docker-stack.yml preprod
@Lucas-C 他们只是警告输出仍将包含您的deploy
和config
键。 如果您运行docker-compose -f docker/prod.yml -f docker/dev.yml config
您可以验证这一点
它用于撰写文件 v3.4 及更高版本。 它支持跨 yaml 引用(部分)。 我完成了这个 zsh 别名/perl 脚本:
alias regen=$'perl -MFile::Slurp=read_file -MYAML=Load,Dump -MHash::Merge::Simple=merge -E \'
local $YAML::QuoteNumericStrings = 1;
$n=read_file("/data/docker-compose.yml");
$s=Dump(merge(map{Load($n.read_file($_))}@ARGV));
local $/ = undef;
$s =~ s/\\bno\\b/"no"/g;
say $s;
\' $(find /data -mindepth 2 -maxdepth 4 -name docker-compose.yml) >! /data/x-docker-compose.yml'
regen
export COMPOSE_FILE=/data/x-docker-compose.yml
优点:perl 是通用工具,所有 perl 模块也是如此,生成速度快。
缺点:我讨厌 hacks,但 DRY 没有其他方法。 最终的 docker-compose 大约有 900 行。 你真的希望我从一开始就支持它作为单个文件吗? 将二进制 docker 与 python docker-compose 与 perl hack 包装在一起是一种耻辱。
你怎么能去掉一个像扩展这样的功能? 这似乎是一个核心功能。
使用docker-compose config
管道到docker stack deploy -c -
的标准输入选项已经解决了我的问题:
docker-compose -f docker-compose.yml \
-f docker-compose.extended.yml \
config \
| docker stack deploy -c - my-stack
我还没有尝试过这个,但我也在docker stack deploy
文档中注意到了这一点:
如果您的配置在多个 Compose 文件之间拆分,例如基本配置和特定于环境的覆盖,您可以提供多个
--compose-file
标志。
以此为例:
docker stack deploy --compose-file docker-compose.yml -f docker-compose.prod.yml vossibility
https://docs.docker.com/engine/reference/commandline/stack_deploy/#compose -file
删除extends
的理由是否记录在某处? 官方文档中似乎没有解释,例如这里: https: //docs.docker.com/compose/extends/#extending -services
如果用户能够理解其中的原理,那么用户就可以更好地了解如何应对删除。 谢谢。
@shaun-blake 我最终使用了多个撰写文件。 这似乎是人们使用的方法。 而不是继承,它更像是一种混合。 在构建或运行时,我将正确的环境 yaml 模板复制到 docker-compose.override.yml。
如果用户能够理解其中的原理,那么用户就可以更好地了解如何应对删除。 谢谢。
+1 关于首先删除extends
理由的文档...
在将近 1 年半之后仍然没有 _extends_。 Cmon,开发人员,您不要在不提供替代方案的情况下删除某事。
他们做到了,他们提供了一种称为组合的替代方案。 请阅读我在线程中的回答。
-菲利波
年7月2018年,在09:41 30日,小慧刘[email protected]写道:
将近 1 年半之后仍然没有延长。 Cmon,开发人员,您不要在不提供替代方案的情况下删除某事。
—
您收到此消息是因为您发表了评论。
直接回复本邮件,在 GitHub 上查看https://github.com/moby/moby/issues/31101#issuecomment-408790200 ,或静音该线程https://github.com/notifications/unsubscribe-auth/AAS_0AOynjpfVnVo4ZqciMbmjBmkcLuJb4Nksmd
@dedalozzo ,“在线程中” == ?
请在此处查看我的评论:
https://github.com/moby/moby/issues/31101#issuecomment -329527600 https://github.com/moby/moby/issues/31101#issuecomment-329527600
基本上,您必须使用一系列 .yml 文件来覆盖或更改容器的配置。
请阅读“指定多个撰写文件”
您可以提供多个 -f 配置文件。 当您提供多个文件时,Compose 会将它们合并为一个配置。 Compose 按照您提供文件的顺序构建配置。 后续文件覆盖并添加到它们的前辈。
https://docs.docker.com/compose/reference/overview/ https://docs.docker.com/compose/reference/overview/
这种方法使用组合而不是继承来获得或多或少相同的结果。
年7月2018年,在15:23 30日,谢尔班Teodorescu [email protected]写道:
@dedalozzo https://github.com/dedalozzo ,“在线程中” == ?
—
你收到这个是因为你被提到了。
直接回复本邮件,在 GitHub 上查看https://github.com/moby/moby/issues/31101#issuecomment-408880809 ,或将线程静音https://github.com/notifications/unsubscribe-auth/AAS_0FZO30NplqHRid_Id8VBOJW7nk5Iks5Iks5Iks5
如果我们结合起来,难道我们不能获得相同的可扩展性吗?
yaml 扩展字段(撰写 2.1+/3.4+)
允许那些x-
字段引用其他文件?
所以我们可以允许一个根include
列表来指定要加载的文件。
它们将被放入x-include
并且可以通过标准 YAML 锚点和合并立即使用。
# /docker-compose.yml
version: '2.1'
volumes:
nginx_file_sockets:
external: false
driver: local
services:
reverse_proxy:
extends:
file: reverse_proxy/docker-compose.yml
service: proxy
restart: 'always'
ports:
- "80:80"
- "443:443"
volumes:
- nginx_file_sockets:/sockets/nginx
reverse_proxy_test:
extends:
file: reverse_proxy/docker-compose.yml
service: proxy
restart: 'always'
ports:
- "8080:80"
- "8443:443"
volumes:
- nginx_file_sockets:/sockets/nginx
web:
extends:
file: webservice/docker-compose.yml
service: app
restart: 'always'
environment:
ENVIRONMENT: 'production'
DB_USER: ${WEB1_DB_USER}
DB_PASSWORD: ${WEB1_DB_PASS}
volumes:
- nginx_file_sockets:/sockets/nginx
web_staging:
extends:
file: webservice/docker-compose.yml
service: app
restart: 'no'
environment:
ENVIRONMENT: 'staging'
DB_USER: ${WEB1_DB_USER}
DB_PASSWORD: ${WEB1_DB_PASS}
volumes:
- nginx_file_sockets:/sockets/nginx
# /proxy/docker-compose.yml
version: '2.1'
services:
proxy:
build: ./
volumes:
- /certs:/certs:ro
# /webservice/docker-compose.yml
version: '2.1'
services:
app:
build:
context: ./folder
args:
LINUX_VERSION: 20.s
LINUX_FLAVOR: dash
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- bootstrap.memory_lock=true
ulimits:
memlock:
soft: -1
hard: -1
# /proxy/docker-compose.yml
version: '3.9'
services:
proxy:
&proxy
build: ./
volumes:
- /certs:/certs:ro
# /webservice/docker-compose.yml
version: '3.9'
services:
app:
&app
build:
context: ./folder
args:
LINUX_VERSION: 20.s
LINUX_FLAVOR: dash
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- bootstrap.memory_lock=true
ulimits:
memlock:
soft: -1
hard: -1
# /docker-compose.yml
version: '3.9'
include:
- /proxy/docker-compose.yml
- /webservice/docker-compose.yml
volumes:
nginx_file_sockets:
external: false
driver: local
services:
reverse_proxy:
<< : *proxy
restart: 'always'
ports:
- "80:80"
- "443:443"
volumes:
- nginx_file_sockets:/sockets/nginx
reverse_proxy_test:
restart: 'always'
<< : *proxy
ports:
- "8080:80"
- "8443:443"
volumes:
- nginx_file_sockets:/sockets/nginx
web:
<< : *app
restart: 'always'
environment:
ENVIRONMENT: 'production'
DB_USER: ${WEB1_DB_USER}
DB_PASSWORD: ${WEB1_DB_PASS}
volumes:
- nginx_file_sockets:/sockets/nginx
web_staging:
restart: 'no'
extends:
file: web1/docker-compose.yml
service: app
environment:
ENVIRONMENT: 'staging'
DB_USER: ${WEB1_DB_USER}
DB_PASSWORD: ${WEB1_DB_PASS}
volumes:
- nginx_file_sockets:/sockets/nginx
@@ /proxy/docker-compose.yml @@
-version: '2.1'
+version: '3.9'
services:
proxy:
+ &proxy
build: ./
volumes:
- /certs:/certs:ro
```
```diff
@@ /webservice/docker-compose.yml @@
-version: '2.1'
+version: '3.9'
services:
app:
+ &app
build:
context: ./folder
args:
LINUX_VERSION: 20.s
LINUX_FLAVOR: dash
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- bootstrap.memory_lock=true
ulimits:
memlock:
soft: -1
hard: -1
```
```diff
@@ /docker-compose.yml @@
-version: '2.1'
+version: '3.9'
+include:
+ - /proxy/docker-compose.yml
+ - /webservice/docker-compose.yml
volumes:
nginx_file_sockets:
external: false
driver: local
services:
reverse_proxy:
- extends:
- file: reverse_proxy/docker-compose.yml
- service: proxy
+ << : *proxy
restart: 'always'
ports:
- "80:80"
- "443:443"
volumes:
- nginx_file_sockets:/sockets/nginx
reverse_proxy_test:
- extends:
- file: reverse_proxy/docker-compose.yml
- service: proxy
+ << : *proxy
restart: 'no'
ports:
- "8080:80"
- "8443:443"
volumes:
- nginx_file_sockets:/sockets/nginx
web:
- extends:
- file: webservice/docker-compose.yml
- service: app
+ << : *app
restart: 'always'
environment:
ENVIRONMENT: 'production'
DB_USER: ${WEB1_DB_USER}
DB_PASSWORD: ${WEB1_DB_PASS}
volumes:
- nginx_file_sockets:/sockets/nginx
web_staging:
- extends:
- file: webservice/docker-compose.yml
- service: app
+ << : *app
restart: 'no'
environment:
ENVIRONMENT: 'staging'
DB_USER: ${WEB1_DB_USER}
DB_PASSWORD: ${WEB1_DB_PASS}
volumes:
- nginx_file_sockets:/sockets/nginx
```
<hr>
Resulting in the final version, which should be already yaml parsable:
```yml
# /docker-compose.yml
version: '3.9'
#include:
# - /proxy/docker-compose.yml
# - /webservice/docker-compose.yml
x-include:
/proxy/docker-compose.yml:
version: '3.9'
services:
proxy:
&proxy
build: ./
volumes:
- /certs:/certs:ro
/webservice/docker-compose.yml:
version: '3.9'
services:
app:
&app
build:
context: ./folder
args:
LINUX_VERSION: 20.s
LINUX_FLAVOR: dash
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- bootstrap.memory_lock=true
ulimits:
memlock:
soft: -1
hard: -1
volumes:
nginx_file_sockets:
external: false
driver: local
services:
reverse_proxy:
<< : *proxy
restart: 'always'
ports:
- "80:80"
- "443:443"
volumes:
- nginx_file_sockets:/sockets/nginx
reverse_proxy_test:
<< : *proxy
restart: 'no'
ports:
- "8080:80"
- "8443:443"
volumes:
- nginx_file_sockets:/sockets/nginx
web:
<< : *app
restart: 'always'
environment:
ENVIRONMENT: 'production'
DB_USER: ${WEB1_DB_USER}
DB_PASSWORD: ${WEB1_DB_PASS}
volumes:
- nginx_file_sockets:/sockets/nginx
web_staging:
<< : *app
restart: 'no'
environment:
ENVIRONMENT: 'staging'
DB_USER: ${WEB1_DB_USER}
DB_PASSWORD: ${WEB1_DB_PASS}
volumes:
- nginx_file_sockets:/sockets/nginx
AFAIK 这是一个 YAML 功能,内置在语言规范本身中,以避免在同一文件中重复部分。 当使用不同的文件时,这基本上是不可能的。
您应该向 YAML 规范本身提出该功能。
这个讨论归结为:
docker-compose -f file.yml
怎么比docker-compose -f file.yml -f file_extension.yml
好这么多?只有在命令行上工作时,不便才会变得显着。 我们必须承认这一点。 无论如何,其他一切都是可编写脚本的。
如果是真正的参数,那么docker-compose up service
具有优于语义docker-compose -f service.yml up
:定义需要的地方发展(又名在命令行)一切docker-compose.override.yml
。
鉴于语义非常清晰且经过深思熟虑。 采用service.yml
_作为命令行使用_可能意味着降低用户体验。 还有另一个论点:虽然乍一看很清楚, docker-compose.yml
是什么, service.yml
可以是任何东西,真的任何东西。
免责声明:一个挑衅性的意见。 :wink: 我没有考虑到所有可能的用例......
经过长时间的讨论,不确定它是否会成功。 恕我直言,extends 很酷,至少必须小心弃用,然后进行讨论,而不是简单地将其丢弃。
我认为我们可以做的一件事是改进关于 v2 与 v3 的文档故事。 许多人认为 v3取代了v2,但这并不完全正确。 两者都获得了专注于其用例的新功能。 这个 GH 问题已经开始,所以我们可以讨论未来需要哪些功能从 docker-compose 进入 Swarm,以及如何改进文档以使用 docker-compose、compose 文件格式和 Swarm 堆栈。 Extends 在最新的 v2.4 中仍然运行良好。 希望我能帮助提供有关我们今天有哪些解决方案的信息:
v2:仅适用于 docker-compose cli。 开发工作流程专注于单个机器和引擎。 也适用于 CI 构建/测试工作流程。 此版本分支最近在 2017 年 12 月在 v17.12 中收到了新功能
v3:非常适合 Swarm/Kube 堆栈,具有多节点概念并保持对大多数 docker-compose cli 功能的支持。
如果您不使用 Swarm 或 Docker Enterprise Kubernetes 堆栈,则没有理由使用 v3 。 坚持使用 v2.4,您将获得所有 docker-compose cli 功能,包括extends、depends_on、扩展字段,甚至带有健康检查的depends_on(以避免等待脚本)。
创建 v3 是为了尝试将单个引擎 docker-compose cli 世界的功能与多节点集群世界合并。 并非所有 v2 功能(如depends_on)在集群中都有意义。 其他功能(如扩展)还没有进入 v3,可能是因为在 v3 存在之前,所有代码都在 docker-compose Python 中,而 v3.0 要支持 Swarm,他们不得不在 docker cli Go 中重写,现在他们在引擎守护进程中再次编写它以最终制作一个尚不存在的 Swarm 堆栈 API。
对于这个问题的新手,还要注意自 3.0 版本以来为解决各种配置、模板和团队工作流问题所做的大量工作:
https://docs.docker.com/compose/extends/#extending -services 上的文档应该以红色强调一个事实,即在 v3 中删除了 extends 关键字,因为它比_note_ 更重要。
我迁移并浏览了文档以了解它为什么不再工作,然后在结束之前遵循几个已解决的问题,然后回到原始文档并注意到措辞。
extends 关键字在 Compose 文件版本 2.1 之前的早期 Compose 文件格式中受支持(请参阅在 v1 中扩展和在 v2 中扩展),但在 Compose 版本 3.x 中不受支持。
可以改写为:
在 Compose 3.x 版中删除了 extends 关键字,但在 Compose 文件版本 2.1 之前的早期 Compose 文件格式中仍受支持(请参阅在 v1 中扩展和在 v2 中扩展)。
这是一个很小的差异,但在浏览文档时很容易被忽略。
@krisrp PR 开始 ^^^
谢谢@BretFisher
是否有计划将 v2 重命名为“version: docker-cli”,将 v3 重命名为“version: swarm/kube”?
考虑到 v3 如何在大多数其他版本控制方案中取代 v2,像这样区分它们会更有意义。 目前两者都在维护和发散,所以除非我弄错了,否则它们似乎都会存在一段时间。
@krisrp相反,增加主要版本号的原因是为了表明兼容性的差异。
@ cpuguy83我不是在暗示别的。 为没有更清楚或明确表示歉意。
多年前,IIRC Gnome 2 和 3 也有这种混乱,当时维护每个的独立分支。
我不想破坏这个线程来讨论版本控制的语义(糟糕的双关语),所以我将把它留在那里。 @BretFisher上周关于改进 v2 与 v3 文档的帖子会对我自己和其他人有所帮助。
@ shin- @cpuguy83一年多之后
我找不到太多关于它的信息,除了“我们可以做不同的事情”(但没有提供实际更好的解决方案)
有技术限制吗? 或者只是缺少拉取请求?
毕竟,我的 compose 2.1 文件仍然运行良好。
不仅如此,更改日志还说“这已被删除,有关详细信息,请参阅‘如何升级’”。 我查看“如何升级”以了解有关如何升级的详细信息,以及“有关详细信息,请参阅‘扩展服务’”的内容。 我转到“扩展服务”,认为我最终会看到一种扩展文件的方法,只是看到“这已被删除,有关详细信息,请参阅更改日志”。
在这一点上,这似乎是文档作者正在玩的一个残酷的笑话。
最终,“堆栈”格式在这里不受控制,它是 Docker CLI 的一部分。
我个人不知道它被排除在 v3 之外的原因......我也不认为我已经看到有人真正尝试将它添加进来。
最好在 docker/cli 中提出这个问题......甚至可能只是一个具有高级文档更改的 PR,就像该功能在那里一样,因此可以讨论它,并且一旦设计获得批准就可以添加实现.
基本上,如果有人想要它,就做一个 PR。 我建议更改文档只是为了确保您不会浪费大量时间以防万一它被拒绝......因为我再次不确定为什么它从 v3 中被省略。
和上面一样。 在再次使用 docker-compose 之前等待这个问题得到解决。
+1 请修复此问题,我们有基于扩展的撰写文件,因此无法将 compose 用于 swarm。
+1 扩展功能
有这方面的消息吗?
还在等它
同样在这里。 还在等。
任何更新?
是否有任何理由说明为什么将其取出?
在 2019 年 8 月 5 日星期一,Jaykishan 的 11:10, notifications @github.com 写道:
任何更新?
—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/moby/moby/issues/31101?email_source=notifications&email_token=ABOE6GA4CXY6ESMZMTDSFGDQC74CZA5CNFSM4DANZGS2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXWZFJK853LNMVXWZFJK83DNRL5WWZFJK853DNRL5
或静音线程
https://github.com/notifications/unsubscribe-auth/ABOE6GCEFFJ3SOLDWRWX2IDQC74CZANCNFSM4DANZGSQ
.
任何更新?
所以……快3年了……
但我仍然希望它能降落 :D
如果它不回来,需要有某种替代扩展。 为什么不允许抽象服务? 文件格式将是扁平的,所有服务声明都将在一个文件中。 您可以将抽象服务与 yaml 为节点添加别名的能力(通过&
)结合使用,并通过<<:
运算符重用这些别名。
为什么是三年!! 看起来你正在工作并且专注于没人关心的事情
这事有进一步更新吗?
这是可悲的。 Terraform 使用组合 - 所以它是可行的,为什么 compose 不能遵循这种良好的设计实践?!
Terraform 模块组成
Terraform 最佳实践
“可怜”,不错。
@Cristian-Malinescu 去吧,请实施它。
这是免费的开源软件。
而不是在这个聊天中像其他人一样抱怨。
真的,这在这里没有任何价值。
正如多次所说,到目前为止没有人想要实现这一点,
所以这只是其他人应该解决的问题,谢谢。
@luckydonald感谢以简单/被动-侵略性的答案推开@Cristian-Malinescu,就像总是没有帮助一样。 @Cristian-Malinescu 这是可行的,因为之前已经完成但已删除,必须(我希望)有一个原因。这个线程上是否有人实际上在 docker-compose 团队中,以便他/她可以阐明事情?
已经提到了略读线程并利用受支持的 YAML 功能。
认为这个例子可能会有所帮助。
@nomasprime谢谢你的发现! 我正在为我的项目在 v2 和 v3 之间做出决定,这解决了这个线程中的大难题。 令人惊讶的是,这些替代解决方案并未在扩展服务功能的官方文档中提及。
很好,听起来是使用文档页面右侧导航栏上的Request docs changes
链接的好机会。
@nomasprime 是的,这个想法之前出现在这个线程中。
如果这可以与其他 yml 文件的文件加载机制相结合,那么这就是拥有所有旧的depends
功能所真正需要的。
见上文,例如https://github.com/moby/moby/issues/31101#issuecomment -413323610
它不会_可读_,但至少_可能_。
@nomasprime谢谢你的发现! 我正在为我的项目在 v2 和 v3 之间做出决定,这解决了这个线程中的大难题。
@arseniybanayev medium 上的文章v2 也支持 anchors 和 extension fields 。 就我而言,我选择 v2(更具体地说是 2.4),因为我使用docker-compose
而不是swarm
(并且 v3 不支持 v2 的某些功能,例如限制容器内存)
并且 v3 不支持 v2 的某些功能,例如限制容器内存
v3 确实支持限制内存,但该字段在deploy -> resources -> limits
https://docs.docker.com/compose/compose-file/#resources 下
@thaJeztah我的意思是, docker-compose
(因为我没有在我之前评论中提到的项目中使用 swarm)。 IIRC 部署仅适用于 swarm,不是吗?
为 swarm 和 local 做一个单独的配置有意义吗? 看来这两者是互相矛盾的。 可以理解,Docker 希望增加 swarm 的使用,但很多人只将 compose 用于本地开发。
我从来没有在 ECS、k8s 或 GAE 的生产环境中使用 swarm 和运行容器。
大多数选项对于 swarm/kubernetes 服务和通过 compose 部署的容器都应该是可翻译/可用的。 我必须检查为什么memory
限制不适用于docker-compose
仍然缺少扩展功能,但对于我的主要用例,我通过COMPOSE_FILE
env 切换到多个 docker compose 文件。 我主要使用它来为 dev 和 prod 使用相同的基本 docker-compose.yml ,并使用不同的密码或配置。
例子:
export COMPOSE_FILE=
docker-compose.yml` # 默认export COMPOSE_FILE=
docker-compose。 yml:docker-compose.prod.yml ` # 使用两个 yaml 文件在docker-compose.prod.yml
我只是用 prod 密码覆盖了环境变量。
这个设置很简单,我不需要总是在docker-compose
命令中添加多个“-f”。 我只需要在开发计算机和服务器上设置不同的COMPOSE_FILE
env var 并且 git 忽略 docker-compose.prod.yml 文件。
还在等:)
我一直在使用它作为扩展的一种方式:
docker-compose \
-f ./docker/base.yml \
-f ./docker/extended.yml \
up
但是在文件中扩展会更好,不需要额外的 bash 脚本。
我也一直在使用它从 bash 脚本动态扩展:
extended_docker_compose="
version: '3.5'
services:
my-service:
restart: always
"
echo "$extended_docker_compose" | docker-compose \
-f ./docker/base.yml \
-f /dev/stdin \
up
@dave-dm 那些是普通的旧覆盖!
我相信这是扩展的潜在有效用例
https://github.com/NerdsvilleCEO/devtools/blob/master/doctl/docker-compose.yml#L10
我有一个docker-compose
包装器,用于服务环境https://github.com/nowakowskir/docker-compose-wrapper
编辑:另一个可能的用例是有人有一个 LAMP/LEMP 堆栈,他们想要扩展这些服务以用于特定服务,例如 wordpress
自 2017 年以来,在探索 docker compose 替代方案时仍在等待。
@nomasprime 是的,这个想法之前出现在这个线程中。
如果这可以与其他 yml 文件的文件加载机制相结合,那么这就是拥有所有旧的
depends
功能所真正需要的。见上文,例如#31101(评论)
它不会_可读_,但至少_可能_。
@luckydonald感谢您指出。 奇怪的是没有内置的 YAML 包含功能,肯定会解决很多问题。
看起来实现第三方解决方案会很容易,但不确定为什么这还没有被带到 v3 🤷♂
一点提醒,很多人会喜欢这个功能:)
不将它移植到 v3 btw 的原因是什么?
我忘记了,但它被带走有真正的原因吗?
在 2020 年 5 月 6 日星期三 23:14 Julien Marechal, notifications@ github.com 写道:
一点提醒,很多人会喜欢这个功能:)
—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/moby/moby/issues/31101#issuecomment-624919070 ,或
退订
https://github.com/notifications/unsubscribe-auth/ABOE6GGDIVGATP734YJA4UTRQHOLJANCNFSM4DANZGSQ
.
与extend
相比,yaml 锚点处理这个用例的方式有点不方便。 在我看来,它的强大主要来自于元素的递归合并。 Anchors 可以让你完成 75% 的工作——它们不会递归地合并 yaml; 您的所有合并都发生在顶层。 引用锚定服务模板然后重新定义environment
块将导致覆盖锚定服务的环境块而不是合并。 您需要在字典的递归树中锚定和引用每个字典,以匹配extend
关键字的行为。
一个例子:
# anchors for the service, environment, deploy, and deploy.placement blocks
# you'll need an anchor for every dict that you want to merge into
x-common-app: &common-app
image: app:1.0
environment: &common-app-environment
common_option: a
overwrite_option: b
deploy: &common-app-deploy
max-replicas-per-host: 3
placement: &common-app-deploy-placement
constraints:
- 'node.labels.app_host==true'
services:
myapp: << *common-app
environment: << *common-app-environment
foo: bar
baz: xyzzy
overwrite_option: quz
deploy: << *common-app-deploy
replicas: 15
placement: << *common-app-deploy-placement
preferences:
- spread: node.labels.region
# The above yields the following:
services:
myapp:
image: app:1.0
environment:
common_option: a
overwrite_option: quz
foo: bar
baz: xyzzy
deploy:
replicas: 15
max-replicas-per-host: 3
placement:
constraints:
- 'node.labels.app_host==true'
preferences:
- spread: node.labels.region
在这个例子中它可能看起来不那么烦人,但如果你在一个扩展块中模板化多个(10+)服务,它会变得烦人并且可读性较差。
在我心目中理想的情况是YAML锚相结合的办法和extend
方法-允许extend
只有从顶层荷兰国际集团x-
前缀扩展字段块,用更智能的合并特性。
在我的组织中,我们发现 yaml 锚点在语法上有点草率,因此我们基本上在外部 Python 脚本中重新实现了extend
功能。 这对我们有用,但这是一种必须处理某些事情的蹩脚方式。 同样,我们必须创建自己的外部工具来处理 v3/Swarm 堆栈的depends_on
删除。
我是从 docker docs 发现这个问题的,在我的情况下,我想模板化我的docker-compose
设置,作为“解决方法”,我遵循了上面的建议,并决定寻找现有的模板程序。 我不会把我们的时间拿回来,所以我详细介绍了我在这里找到的一些内容,不管关于这个实际功能请求的任何讨论,但是,涉及到的人可能会觉得使用基于 YAML 的模板系统来生成一个撰写文件而不是将此功能集成到docker-compose
本身可能更适合封装和为工作选择正确的工具。
在某些情况下,我使用了一个基本的反向代理与 Let's Encrypt 和几个应用程序容器(现在是 Nextcloud,一个给我,一些单独的给朋友) - 在这种情况下,我想制作一个 Nextcloud 容器的模板,所以对于非常相似的设置,我可以避免错误和重复击键。 以下软件包是我尝试过的:
ytt 看起来非常全面,是本地使用 YAML 的唯一选择。 它看起来功能强大,是完成这项工作的正确工具,它使用 Starlark(Python 的超集)直接在 YAML 文件中执行处理。 然而没过多久,模板就变得很乱,乱七八糟的代码片段和YAML的片段,加上字典和数组等Python数据类型和YAML片段的混合(似乎有点像文本处理,有点像使用一个输出像字符串这样的标签的 HTML 模板引擎最终导致了太多的错误和太乱的文件。 Dhall 看起来也很全面,使用独特的母语,可以输出多种格式; 它看起来更像是一种元编程语言而不是模板系统,但是鉴于语法是功能性的并且它的类型非常严格,它很快变得比非结构化 YAML 的简单模板的价值更复杂。 看起来有点像 JSON 和 Haskell 的混合体,它需要太多的思考才能将我需要完成的工作融入到语言中。
有趣的是,Dhall 和 ytt 都很难使用参数化字段名称,否则两者都可以很好地工作,但是我需要让我的实例名称出现在服务名称和卷名称中,并且在这两者中都可以实现这有点难看; 使用散列中的值的参数很容易,但是在键名中使用这些参数很麻烦,或者我找不到如何巧妙地做到这一点,加上 Dhall 强制执行类型安全,这与该概念背道而驰。 使用 Jsonnet 很简单,只需将表达式放在方括号中即可。
CUE 和 Jsonnet 都是面向 JSON 的,但是通过转换器运行它们一点也不难,而且看起来和 Dhall 一样,CUE 有很多强大的功能,并且是从 Jsonnet 的缺点中诞生的,但是在文档中的一部分,很明显这已经是矫枉过正了; 也许有更多的时间来正确学习它会是更好的选择,但似乎 CUE 更倾向于验证和模式而不是简单的模板作业,所以我很快转移到 Jsonnet 并很快完成了这项工作。
最后,只有在我完成所有这些之后,我才意识到我一直在将这些工具与 Liquid 标签或类似 HTML 模板的简单性进行比较,我实际上可能一开始就简单地使用 Liquid。 我只在 Jekyll 站点的上下文中使用它,所以它从来没有发生过我没有获得独立的包,但是有了基本的循环和列表,以及将表达式直接评估为就地文本的能力,这可能会对这份工作也好得多; Jsonify 可能优于 JSON,但 Liquid 可以在纯 YAML 中运行,因此文件再次变得更具可读性。
+1 docker-compose 是我在工作中实施的定制解决方案背后的一个灵感,因为创建这张票是为了支持将大量测试环境迁移到 k8s。 我非常小心地避免花里胡哨,但很快就证明了一个类似的功能是合理的。 哲学讨论(组合与继承等)在我看来就像是对常识的分心(事后看来 - 近 3 年后仍未解决)。 显然,可能会继续使用 docker-compose 的人需要它。
+1:+1:
我之前在dev
/ test
/ ci
环境中大量使用了此功能,我可以在其中从./config/{dev,test,ci}/compose.yaml
子目录路径中的撰写文件进行扩展。 我会有一个.env
有COMPOSE_ENV=dev
,但开发人员可以覆盖,显然我会覆盖ci
。
我对弃用该功能而不是用可以做类似事情的东西替换它感到震惊。 也许只是允许我们使用 jinja2 并做我们想做的事。 我希望 Docker-Compose 不那么反 DRY。 :'(
似乎docker-compose
从 v1.27 开始支持extends
(https://github.com/docker/compose/pull/7588)。
我大量使用该功能的一个用例是将 docker 图像版本化为代码。 我的 docker dev 和 prod compose 文件都从 docker-images.yml 扩展,其中只列出了基本服务和服务图像的标记版本。
在 v3 中没有找到一个简单的解决方法。
最有用的评论
不仅如此,更改日志还说“这已被删除,有关详细信息,请参阅‘如何升级’”。 我查看“如何升级”以了解有关如何升级的详细信息,以及“有关详细信息,请参阅‘扩展服务’”的内容。 我转到“扩展服务”,认为我最终会看到一种扩展文件的方法,只是看到“这已被删除,有关详细信息,请参阅更改日志”。
在这一点上,这似乎是文档作者正在玩的一个残酷的笑话。