Docker 无法从env_文件中声明的文件中读取环境变量

Docker 无法从env_文件中声明的文件中读取环境变量,docker,docker-compose,environment-variables,Docker,Docker Compose,Environment Variables,在我的docker-compose.yml中,我定义了两个服务,app和db 版本:3.7 服务: 应用程序: 图片:我的应用程序 容器名称:我的应用程序 端口: -${MY_PORT}:${MY_PORT} 环境文件: -//app.env ... 取决于: -分贝 环境: -数据库_URL=${DB_URL} db: 图片:my_db 容器名称:my db 环境文件: -./db.env 端口: -${DB\u PORT}:${DB\u PORT} 如上所示,我在app和db服务的env_f

在我的docker-compose.yml中,我定义了两个服务,app和db

版本:3.7 服务: 应用程序: 图片:我的应用程序 容器名称:我的应用程序 端口: -${MY_PORT}:${MY_PORT} 环境文件: -//app.env ... 取决于: -分贝 环境: -数据库_URL=${DB_URL} db: 图片:my_db 容器名称:my db 环境文件: -./db.env 端口: -${DB\u PORT}:${DB\u PORT} 如上所示,我在app和db服务的env_file选项中定义了两个env文件app.env和db.env

app.env:

MY_端口=8081 db.env:

DB_端口=4040 数据库地址=postgres://myapp:app@db:4040/myapp 我想检查docker compose是否能够成功读取环境变量。因此,我运行docker compose config命令。然而,输出是

$docker编写配置 警告:未设置MY_PORT变量。默认为空字符串。 警告:未设置DB_URL变量。默认为空字符串。 警告:未设置DB_端口变量。默认为空字符串。 错误:合成文件“./docker Compose.yml”无效,因为: services.app.ports无效:无效端口:,应为[[remote_ip:]remote_port[-remote_port]:]端口[/protocol] services.db.ports无效:无效端口:,应为[[remote\u ip:]remote\u port[-remote\u port]:]端口[/protocol] 为什么docker compose无法从我在docker-compose.yml的env_file选项中声明的那些env文件中读取环境变量


此外,我还有另一个问题,那就是我知道通常环境文件不应该是版本控制的,因为它可能包含凭证。env文件通常应如何用于不同的环境,例如开发、暂存和生产环境?对不同的环境进行成像时,这些变量的值不同。有人能提供一些例子吗?

失败的原因是您正在定义外部命名app.env和db.env文件的环境变量,并在env_文件选项中指定,仅在已启动的容器内设置,并且在docker compose解析时不用于docker-compose.yml文件内的变量扩展

这很容易与在docker-compose.yml文件的相同位置提供名为.env的文件的选项混淆。由于docker compose将在docker-compose.yml文件旁边或使用-f开关指定的文件旁边查找一个名为.env的文件,并在解析docker-compose.yml文件之前使用该文件中的环境变量进行变量扩展

换言之:

env_文件选项 将在容器中设置环境变量,这只是一个方便的功能,允许您从docker-compose.yml文件中外部化环境变量 在docker compose解析之前,这些文件中的环境变量不会用于docker-compose.yml文件中的变量扩展。 .env文件 解析前将用于docker-compose.yml文件中的环境变量扩展。 不会在已启动的容器内设置环境变量。 第一个问题的建议解决办法 如果您将值迁移到单个.env文件中,并将其放置在与docker-compose.yml文件相同的目录中,则应该可以这样做

第二个问题 我理解您的第二个问题,您正在询问如何使用.env文件或env_文件选项为您的不同环境配置服务

我不认为有一个简单和单一的答案。它可以通过多种方式解决。但这也取决于您要部署到什么?是库伯内特斯吗?码头工人群?或者只是一个单节点docker主机

Kubernetes和Docker swarm有不同的方法来帮助你解决这个问题

这些都是高度安全的解决方案,其中机密的操作员可以受到限制,并且没有访问权限的开发人员或操作员不会看到这些机密

但是对于单节点docker主机,不在swarm模式下运行机密只在swarm模式下工作,没有很多新奇的选择。据我所知,在构建和部署管道时,您必须非常手动地管理这一点

您的服务的敏感配置不应该与服务定义放在同一个存储库中,这是正确的。数据库的根密码或生产环境的服务发现服务的凭据等不需要位于源旁边

传统上,另一个存储库将包含此内容—为您提供了限制具有此访问权限的人群的机会。构建/部署服务器/服务将签出您的服务的新版本,可能会构建它,然后签出配置存储库,并从那里使用配置启动服务 . 并且,确保随后删除配置文件

这就是我推荐的单节点docker主机部署机制的解决方案——两个存储库,以及一些脚本,确保在部署过程中放置正确的.env文件,然后再次删除


我希望这会有所帮助?

失败的原因是您正在定义外部命名app.env和db.env文件的环境变量,并在env_文件选项中指定,仅在已启动的容器内设置,并且在docker compose解析时不用于docker-compose.yml文件内的变量扩展

这很容易与在docker-compose.yml文件的相同位置提供名为.env的文件的选项混淆。由于docker compose将在docker-compose.yml文件旁边或使用-f开关指定的文件旁边查找一个名为.env的文件,并在解析docker-compose.yml文件之前使用该文件中的环境变量进行变量扩展

换言之:

env_文件选项 将在容器中设置环境变量,这只是一个方便的功能,允许您从docker-compose.yml文件中外部化环境变量 在docker compose解析之前,这些文件中的环境变量不会用于docker-compose.yml文件中的变量扩展。 .env文件 解析前将用于docker-compose.yml文件中的环境变量扩展。 不会在已启动的容器内设置环境变量。 第一个问题的建议解决办法 如果您将值迁移到单个.env文件中,并将其放置在与docker-compose.yml文件相同的目录中,则应该可以这样做

第二个问题 我理解您的第二个问题,您正在询问如何使用.env文件或env_文件选项为您的不同环境配置服务

我不认为有一个简单和单一的答案。它可以通过多种方式解决。但这也取决于您要部署到什么?是库伯内特斯吗?码头工人群?或者只是一个单节点docker主机

Kubernetes和Docker swarm有不同的方法来帮助你解决这个问题

这些都是高度安全的解决方案,其中机密的操作员可以受到限制,并且没有访问权限的开发人员或操作员不会看到这些机密

但是对于单节点docker主机,不在swarm模式下运行机密只在swarm模式下工作,没有很多新奇的选择。据我所知,在构建和部署管道时,您必须非常手动地管理这一点

您的服务的敏感配置不应该与服务定义放在同一个存储库中,这是正确的。数据库的根密码或生产环境的服务发现服务的凭据等不需要位于源旁边

传统上,另一个存储库将包含此内容—为您提供了限制具有此访问权限的人群的机会。构建/部署服务器/服务将签出您的服务的新版本,可能会构建它,然后签出配置存储库并从那里使用配置启动服务。并且,确保随后删除配置文件

这就是我推荐的单节点docker主机部署机制的解决方案——两个存储库,以及一些脚本,确保在部署过程中放置正确的.env文件,然后再次删除


我希望这会有所帮助?

您能否使用docker engine 18.06.0+将版本1更改为版本3.7并重新更改,问题相同。您能否使用docker engine 18.06.0+将版本1更改为版本3.7并重新更改,问题相同。谢谢。我了解.env的用法,实际上这是我最初的解决方案,然后我希望有一个类似.env的外部文件,但用于不同的环境,例如,登台、生产,这就是为什么我现在改为使用它的原因。但是你能为我在帖子中的第二个问题提供一个答案吗?我完全明白你的意思——我曾经试图这么做。这似乎是docker compose支持的一个非常好的特性。现在,我必须以其他方式配置环境。我整理了一下答案——稍后我将在另一次编辑中回答您的另一个问题。我发布了我对第二个问题的想法和见解,这确实应该放在自己的问题中——但也许您可以告诉我您的托管解决方案是什么样的?这是一个实验性的单主机设置吗?你只是想用正确的方式学习?还是别的什么?谢谢!它是一个单一的主机,在我的项目中不需要群集模式。你的建议很有道理:你说数据库等敏感配置
用户名密码传统上,另一个存储库会包含这个,嗯…我注意到在互联网上有人建议根本不让他们在互联网上,那就是为了安全起见,在任何回购协议中都不进行版本控制,您觉得这是一个不太传统的解决方案吗?我个人喜欢在由源代码管理系统控制的文件中定义构成我的设置的所有内容。这样,我可以在任何给定的时间从无到有地重新创建堆栈。我认为这是一种弹性措施。我想强调的是,git存储库不必驻留在远程服务器上——您可以在本地服务器上创建存储库,也可以在同一个专用网络上的附近服务器上创建存储库。我不认为让文件在部署服务器上不受控制是一个好主意。如果你把它们弄松了,那又怎么样?下节继续,谢谢。我了解.env的用法,实际上这是我最初的解决方案,然后我希望有一个类似.env的外部文件,但用于不同的环境,例如,登台、生产,这就是为什么我现在改为使用它的原因。但是你能为我在帖子中的第二个问题提供一个答案吗?我完全明白你的意思——我曾经试图这么做。这似乎是docker compose支持的一个非常好的特性。现在,我必须以其他方式配置环境。我整理了一下答案——稍后我将在另一次编辑中回答您的另一个问题。我发布了我对第二个问题的想法和见解,这确实应该放在自己的问题中——但也许您可以告诉我您的托管解决方案是什么样的?这是一个实验性的单主机设置吗?你只是想用正确的方式学习?还是别的什么?谢谢!它是一个单一的主机,在我的项目中不需要群集模式。你的建议很有道理:你说敏感配置,例如数据库用户名密码,传统上,另一个存储库会包含这个,嗯……我注意到在互联网上有人建议根本不让他们在互联网上,那就是说,为了安全起见,不要在任何回购协议中对其进行版本控制,您觉得这是一个不太传统的解决方案吗?我个人喜欢在由源代码管理系统控制的文件中定义构成我的设置的所有内容。这样,我可以在任何给定的时间从无到有地重新创建堆栈。我认为这是一种弹性措施。我想强调的是,git存储库不必驻留在远程服务器上——您可以在本地服务器上创建存储库,也可以在同一个专用网络上的附近服务器上创建存储库。我不认为让文件在部署服务器上不受控制是一个好主意。如果你把它们弄松了,那又怎么样?在下一篇评论中继续