我有以下项目目录结构:
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
答案 0 :(得分:2)
Compose 有两个单独的 environment file 处理层:
docker-compose.yml
文件被读入时,它从与 .env
相同的目录中读取一个 docker-compose.yml
文件,并使用它来扩展 $VARIABLE
引用。立>
env_file:
并使用它来设置容器中的环境变量。由于 .env
与 docker-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
打印出其环境而不是启动数据库。我希望您在这里看到的流程是:
docker/.env
(来自与 docker-compose.yml
文件相同的目录),该文件不存在MYSQL_USER
是一个空字符串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 文件所在的位置。