无法从 env_file 中声明的文件中读取环境变量 [英] Failed to read environment variables from the file declared in env_file

查看:38
本文介绍了无法从 env_file 中声明的文件中读取环境变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

版本:3.7";服务:应用程序:图片:my_app容器名称:我的应用端口:- ${MY_PORT}:${MY_PORT}环境文件:- ./app.env...依赖于取决于:- D b环境:- DATABASE_URL=${DB_URL}D b:图片:my_db容器名称:我的数据库环境文件:- ./db.env端口:- ${DB_PORT}:${DB_PORT}

如上所示,我在 env_file 选项中定义了两个 env 文件,app.envdb.envcode>app 和 db 服务.

app.env:

MY_PORT=8081

db.env:

DB_PORT=4040DB_URL=postgres://myapp:app@db:4040/myapp

我想检查我的docker-compose是否可以成功读取环境变量.所以,我运行命令 docker-compose config.但是输出是

$ docker-compose config警告:未设置 MY_PORT 变量.默认为空字符串.警告:未设置 DB_URL 变量.默认为空字符串.警告:未设置 DB_PORT 变量.默认为空字符串.错误:撰写文件./docker-compose.yml"无效,因为:services.app.ports 无效:无效的端口:",应该是 [[remote_ip:]remote_port[-remote_port]:]port[/protocol]services.db.ports 无效:无效的端口:",应该是 [[remote_ip:]remote_port[-remote_port]:]port[/protocol]

为什么我的 docker compose 无法从我在 docker-compose.yml 的 env_file 选项中声明的那些 env 文件中读取环境变量?

此外,我还有一个问题,那就是我明白通常情况下 env 文件不应该受版本控制,因为它可能包含凭据.env 文件通常应该如何用于不同的环境,例如开发、暂存和生产环境?成像不同的环境对这些变量具有不同的值.有人可以提供一些例子吗?

解决方案

失败的原因是你定义的环境变量名为 app.envdb.env 文件,并在 env_file 选项中指定,仅在启动的容器内设置 - 不用于 docker-compose 内的变量扩展.由 docker-compose 解析的 yml 文件.

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

换句话说:

env_file 选项

  • 将在您的容器内设置环境变量,这只是一个方便的功能,允许您从 docker-compose.yml 文件中外部化环境变量
  • 在被 docker-compose 解析之前,这些文件中的环境变量将用于docker-compose.yml文件中的变量扩展.

.env 文件

  • 解析前将用于docker-compose.yml文件内的环境变量扩展.
  • 在启动的容器内设置环境变量.

第一个问题的建议解决方案

如果您将值迁移到单个 .env 文件中,并将其放在与 docker-compose.yml 文件相同的目录中,这应该可以工作.

第二个问题

据我了解您的第二个问题,您是在询问应该如何使用 .env 文件或 env_file 选项为您的不同环境配置服务.

我不认为对此有一个简单而单一的答案.它可以通过多种方式解决.但这也取决于您要部署到什么地方?是 Kubernetes 吗?Docker 群?还是只是一个单节点 docker 主机?

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

那些是高度安全的解决方案,可以限制机密的操作者,并且开发者或无权访问的操作者不会看到机密.

但是对于单节点 docker 主机,不是在 swarm 模式下运行(secrets 只在 swarm 模式下工作),真的没有很多花哨的选择.据我所知,您必须在构建和部署管道中手动管理它.

您的服务的敏感配置不应该与服务定义放在同一个存储库中,这是对的.数据库的 root 密码或生产环境的服务发现服务的凭据等内容不需要与源相邻.

传统上,另一个存储库将包含此 - 让您有机会限制具有此访问权限的人群.构建/部署服务器/服务将检出您的服务的新版本,或许构建它,然后检出配置存储库并使用从那里的配置启动服务.并且,确保之后删除配置文件.

这将是我为单节点 docker 主机部署机制推荐的解决方案 - 两个存储库,以及一些确保在部署期间放置正确的 .env 文件并再次删除的脚本.

我希望这有帮助吗?

In my docker-compose.yml, I defined two services, app and db.

version: "3.7"

services:
  app:
    image: my_app
    container_name: my-app
    ports:
      - ${MY_PORT}:${MY_PORT}
    env_file:
      - ./app.env
    ...
    depends_on:
      - db
    environment:
      - DATABASE_URL=${DB_URL}
  db:
    image: my_db
    container_name: my-db
    env_file:
      - ./db.env
    ports:
      - ${DB_PORT}:${DB_PORT}

As you can see above, I have defined two env files, app.env and db.env in the env_file option of app and db services.

app.env:

MY_PORT=8081

db.env:

DB_PORT=4040
DB_URL=postgres://myapp:app@db:4040/myapp

I want to check if my docker-compose can successfully read the environment variables. So, I run the command docker-compose config. However the output is

$ docker-compose config
WARNING: The MY_PORT variable is not set. Defaulting to a blank string.
WARNING: The DB_URL variable is not set. Defaulting to a blank string.
WARNING: The DB_PORT variable is not set. Defaulting to a blank string.
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.app.ports is invalid: Invalid port ":", should be [[remote_ip:]remote_port[-remote_port]:]port[/protocol]
services.db.ports is invalid: Invalid port ":", should be [[remote_ip:]remote_port[-remote_port]:]port[/protocol]

Why my docker compose can't read environment variables from those env files I declared in the env_file option in my docker-compose.yml?

Besides, I have another question, that's I understand that normally the env file shouldn't be version controlled since it could contain credentials. How normally should the env file be used for different environment e.g. development, staging and production environments? Imaging different environment has different values for those variables. Could someone please provide some examples?

解决方案

The reason this is failing, is that the environment variables that you are defining the the external named app.env and db.env files, and specifying in the env_file option, are only being set inside the container that is started - and are not used for variable expansion inside the docker-compose.yml file when parsed by docker-compose.

This is easily confused with the option of supplying a file named .env in the same location as the docker-compose.yml file. Since docker-compose will look for a file specifically named .env next to the docker-compose.yml file (or next to the file that you are specifying with the -f switch) - and use the environment variables in that file for variable expansion in the docker-compose.yml file, before parsing it.

In other words:

The env_file option

  • Will set environment variables inside your container, is is just a convenience feature that allows you to externalise the environment variables from the docker-compose.yml file
  • Environment variables in these files will NOT be used for variable expansion in the docker-compose.yml file before parsed by docker-compose.

The .env file

  • Will be used for environment variable expansion inside the docker-compose.yml file before parsing.
  • Will NOT set environment variables inside the started container.

Suggested solution to the first question

If you migrate your values into a single .env file and place it in the same directory as your docker-compose.yml file, this should work.

Second question

As I understand your second question, you are asking how the .env file, or the env_file option should be used to configure your services for your different environments.

I do not think that there is a simple and single answer to this. It can be solved in a number of ways. But it also depends on what you are deploying to? Is it kubernetes? Docker swarm? Or just a single node docker host?

Kubernetes and Docker swarm have different means of helping you out with this.

Those are highly secure solutions, where operators of the secrets can be limited, and the secrets will not be seen by developers or operators that do not have access.

But for the single node docker host, not operating in swarm mode (secrets only work in swarm mode), there really isn't a lot of fancy options. You will have to manage this pretty manually in your build and deploy pipes as far as I am aware.

You are right that the sensitive configuration of your services, should not go in the same repository as the service definition. Things like root password for a database, or credentials to your service discovery service for your production environment do not need to live next to the sources.

Traditionally, another repository would contain this - giving you the oppotunity to limit the group of people that have this access. The build/deployment server/service will check out the new revision of your service, build it perhaps, and then check out the configuration repository and start the services with the configurations from there. And, make sure to remove the configuration files afterwards.

That would be the solution I would recommend for a single node docker host deployment regime - two repositories, and some scripting that ensures that the correct .env file is put in place during deployment, and removed again.

I hope this is helpful?

这篇关于无法从 env_file 中声明的文件中读取环境变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆