Failed to read environment variables from the file declared in env_file

坚强是说给别人听的谎言 提交于 2021-02-05 08:10:55

问题


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?


回答1:


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.

  • Kubernetes secrets
  • Docker swarm secrets

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?



来源:https://stackoverflow.com/questions/62518965/failed-to-read-environment-variables-from-the-file-declared-in-env-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!