docker compose 覆盖端口属性而不是合并它

Posted

技术标签:

【中文标题】docker compose 覆盖端口属性而不是合并它【英文标题】:docker compose override a ports property instead of merging it 【发布时间】:2018-07-28 19:17:57 【问题描述】:

我的 docker compose 配置如下所示:

docker-compose.yml

version: '3.5'

services:
    nginx:
        ports:
            - 8080:8080

docker-compose.prod.yml

version: '3.5'

services:
    nginx:
        ports:
            - 80:80

现在,当我运行命令:docker-compose -f docker-compose.yml -f docker-compose.prod.yml up 时,nginx 在主机上公开两个端口:800080,因为它合并了端口属性:

version: '3.5'

services:
    nginx:
        ports:
            - 8080:8080
            - 80:80

有没有办法覆盖它?我只想公开端口80

【问题讨论】:

【参考方案1】:

此行为记录在 https://docs.docker.com/compose/extends/#adding-and-overriding-configuration

对于多值选项portsexposeexternal_linksdnsdns_searchtmpfs,Compose 会连接两组值

由于ports 将是您所有撰写文件中端口的串联,我建议创建一个包含您的开发端口映射的新docker-compose.dev.yml 文件,将它们从基础docker-compose.yml 文件中删除。

作为Nikson says,您可以将其命名为docker-compose.override.yml 以自动应用您的开发配置,而无需链接docker-compose 文件。如果您手动指定另一个覆盖文件(例如docker-compose -f docker-compose.yml -f docker-compose.prod.yml),则不会应用docker-compose.override.yml

【讨论】:

【参考方案2】:

暂时不可能,但我找到了使用命令yq 解决此问题的好方法。 您需要从原始文件中删除端口。

示例: 请注意,此命令将从您当前的 docker-compose.yml 中删除 nginx 端口(因为 -i 选项)

yq e -i 'del(.services.nginx.ports)' docker-compose.yml

您可以在部署脚本上执行此命令,也可以在 docker-compose up -d 之前手动执行此命令

在 docker-compose 上还有一个开放的issue,您可能需要不时查看一下。

【讨论】:

【参考方案3】:

只需保持docker-compose.yml 超级简单,并将端口添加到另一个文件docker-compose.develop.yml 中,然后像docker-compose -f docker-compose.yml -f docker-compose.develop.yml up 一样运行它。 这样您就可以将其与您的docker-compose.override.yml 文件分开。

所以你将三个文件:

|- docker-compose.yml # no ports specified
|- docker-compose.override.yml # ports 8080:8080
|- docker-compose.develop.yml #ports 80:80

更多解释请参考这篇文章:https://mindbyte.nl/2018/04/04/overwrite-ports-in-docker-compose.html

【讨论】:

【参考方案4】:

我也遇到过同样的问题。使用docker-compose.override.yml 提出的解决方案听起来不错,也是官方解决方案。

虽然对于我自己的一些项目,我已经应用了erb 模板引擎来为多个环境编译docker-compose.yml.erb 文件。简而言之,我使用:

COMPOSE_TEMPLATE_ENV=production erb docker-compose.yml.erb > docker-compose.yml
COMPOSE_TEMPLATE_ENV=production erb docker-compose.yml.erb > docker-compose-production.yml

然后我可以在我的模板中使用ENV['COMPOSE_TEMPLATE_ENV'] 以及ERB 的语法,因此只需配置一个文件,无需担心正确地填充它们。 Here's the short post article I've written about it

【讨论】:

【参考方案5】:

使用.override.yml 文件覆盖属性并且需要覆盖属性的明确分隔

docker-compose.override.yml

例子:

version: '3.5'

services:
    nginx:
        ports:
            - 80:80

默认值:

docker-compose up

将使用您的 docker-compose.ymldocker-compose.override.yml 文件

参考:docker-compose multiple compose

【讨论】:

这并不能解决他们的 prod 配置接收原始文件和覆盖文件中的端口连接的问题。 @RachSharp,他建议从docker-compose.yml 中删除端口,只将它们放在docker-compose.override.yml 中。所以当你 concat docker-compose.yml 和 docker-compose.prod.yml` 时,你只会得到 prod 端口。 有点牵强,没有提到任何关于从docker-compose.yml 中删除端口或如何在未在产品上运行时使用端口8080

以上是关于docker compose 覆盖端口属性而不是合并它的主要内容,如果未能解决你的问题,请参考以下文章

为啥安装了 Docker 而不是 Docker Compose?

在文件'./docker-compose.yml'中,服务'proxy-nginx'必须是映射而不是字符串?

Nginx 寻找文件而不是端点?

杂谈3-docker compose 启动容器失败(端口被占用)

为啥 docker-compose 不会为 mongo 打开端口?

向 docker-compose.yml 公开随机端口