Docker Compose 似乎没有读取 env 文件中定义的环境变量

时间:2021-06-03 10:51:59

标签: docker docker-compose

我有以下项目目录结构:

myapp/
    docker/
        docker-compose.yml
    .env
    src/
        <my source code here>
    config.properties

这是我的 .env 文件:

ENV=local
SERVICE_DB_HOST=0.0.0.0
SERVICE_DB_PORT=3306
SERVICE_DB_ROOT_PASSWORD=12345
SERVICE_DB_APP_USER=my-service-user
SERVICE_DB_APP_PASSWORD=23456

这是我的docker/docker-compose.yml

version: "3.7"
services:
  myapp-main-db:
    env_file:
      - ../.env
    image: mysql:8
    container_name: myapp-main-db
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    ports:
      - $SERVICE_DB_PORT:$SERVICE_DB_PORT
    environment:
      MYSQL_ROOT_PASSWORD: $SERVICE_DB_ROOT_PASSWORD
      MYSQL_DATABASE: myapp_service_db_$ENV
      MYSQL_USER: $SERVICE_DB_APP_USER
      MYSQL_PASSWORD: $SERVICE_DB_APP_PASSWORD
    volumes:
      - myapp-service-db-data:/var/lib/mysql
volumes:
  myapp-service-db-data:

当我从项目根目录运行 docker-compose -f docker/docker-compose.yml up -d 时,我看到 MySQL 容器正常启动,并通过 docker ps 验证其运行。

但是我无法使用预期的连接字符串和凭据连接到它,我确定是正确的。这让我相信 Docker Compose 没有像我期望的那样加载 ../.env 文件,因此 ../.env 中定义的任何变量都没有作为环境变量注入。

有人能看出我哪里出错了吗?

更新

当我运行 docker-compose config 时,我得到:

$ docker-compose config
WARNING: The SERVICE_DB_PORT variable is not set. Defaulting to a blank string.
WARNING: The SERVICE_DB_ROOT_PASSWORD variable is not set. Defaulting to a blank string.
WARNING: The ENV variable is not set. Defaulting to a blank string.
WARNING: The SERVICE_DB_APP_USER variable is not set. Defaulting to a blank string.
WARNING: The SERVICE_DB_APP_PASSWORD variable is not set. Defaulting to a blank string.
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.myapp-main-db.ports contains an invalid type, it should be a number, or an object

3 个答案:

答案 0 :(得分:2)

Compose 有两个单独的 environment file 处理层:

  1. docker-compose.yml 文件被读入时,它从与 .env 相同的目录中读取一个 docker-compose.yml 文件,并使用它来扩展 $VARIABLE 引用。
  2. 启动单个容器时,它会读取 env_file: 并使用它来设置容器中的环境变量。

由于 .envdocker-compose.yml 文件不在同一目录中,Compose 在扩展文件中的变量之前不会读取它。这会导致容器获取数据库凭据的空字符串,并且由于 ports: 格式错误而导致错误。

您可以将 .env 移动到与 docker-compose.yml 相同的目录

mv .env docker
docker-compose -f docker/docker-compose.yml up

或传递一个 docker-compose --env-file 选项

docker-compose -f docker-docker-compose.yml --env-file .env up

您不需要 env_file: 文件中的 docker-compose.yml 用于此特定用途并且可以将其删除。


要进一步调试,您可以docker-compose run 一个带有备用command: 的容器。例如,您可以 docker-compose run myapp-main-db env 打印出其环境而不是启动数据库。我希望您在这里看到的流程是:

  1. Compose 读取 docker/.env(来自与 docker-compose.yml 文件相同的目录),该文件不存在
  2. Compose 替换文件中的变量;我希望看到 MYSQL_USER 是一个空字符串
  3. Compose 读取 env_file:;容器将具有来自该文件的附加环境变量 SERVICE_DB_APP_USER=my-service-user

答案 1 :(得分:1)

根据 docker 的默认行为,Dockerfile 和 docker-compose 从不从父目录读取任何文件或值。它总是从当前目录或子目录读取。

所以对于您的代码,我建议请在源/根目录中使用 docker-compose 文件。

示例:

myapp/
    docker-compose.yml
    .env
    src/
        <my source code here>
    config.properties

答案 2 :(得分:1)

引自 Docker 官方文档:Using the “--env-file” option

<块引用>

您可以在任何地方使用 .env 文件,使用 --env-file 选项:

通过将文件作为参数传递,您可以将其存储在任何位置并命名 它适当地,例如,.env.ci、.env.dev、.env.prod。通过 文件路径是使用 --env-file 选项完成的:

docker-compose --env-file ./config/.env.dev up

显然,当您在 docker-compose 中时,您不能去当前目录的父目录获取 .env 文件,因此,不是像这样:

version: "3.7"
services:
  myapp-main-db:
    env_file:
      - ../.env

在父文件夹中使用其他位置的 .env 文件的一种方法是使用 --project-directory 命令的 docker-compose 参数。根据{{​​3}}:

<块引用>

.env 文件路径如下:

从+v1.28开始,.env文件放在项目的基础上 目录

对于以前的版本,它放在当前工作中 执行 Docker Compose 命令的目录除非 --project-directory 定义为覆盖 .env 文件的路径。 +v1.28 通过限制 项目目录的文件路径。"

这对您来说意味着:

docker-compose --project-directory .. up

或者:如果您将其作为 --env-file 命令的 docker-compose 参数传递,您可以访问系统上的任何 .env 文件。

docker-compose --env-file ../.env up

如果您既不使用 --project-directory 也不使用 --env-file,则需要将 .env 文件放在 docker-compose 文件所在的位置。