难以理解 Docker 编写环境变量
Trouble understanding Docker Compose environment variables
我有一个 playground 项目 Docker 使用这样的文件编写:
version: '3'
services:
mysql:
image: 'mysql:8'
container_name: '${PROJECT_NAME}_mysql'
hostname: '${PROJECT_NAME}_mysql'
networks:
- internal
ports:
- '127.0.0.1:${MYSQL_EXPOSE_PORT}:3306'
volumes:
- mysql:/var/lib/mysql
env_file:
- ./mysql/.env
environment:
MYSQL_EXPOSE_PORT: '${MYSQL_EXPOSE_PORT}'
MYSQL_ROOT_PASSWORD: '${MYSQL_ROOT_PASSWORD}'
MYSQL_USER: '${MYSQL_USER}'
MYSQL_PASSWORD: '${MYSQL_PASSWORD}'
volumes:
mysql:
networks:
internal:
我的./mysql/.env
是这样的:
MYSQL_DATABASE=foobar
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=web
MYSQL_PASSWORD=web
我的 .env
文件如下所示:
COMPOSE_PROJECT_NAME=foobar
PROJECT_NAME=foobar
MYSQL_EXPOSE_PORT=33061
MYSQL_DATABASE=foobar
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=web_override
MYSQL_PASSWORD=web_override
我在某处读到 env_file
和 environment
创建的变量将在容器本身中可用,而 --env-file
提供在处理 [=20] 期间可用的变量=] 文件.
但是 运行 :
docker-compose -f docker-compose.yml --env-file .env up -d
对我来说,产生了意想不到的行为。
如果我同时省略 env_file
和 environment
配置,MySQL 将因密码为空而无法启动。来自 --env-file
的变量将被忽略。这是否意味着实际上需要 MYSQL_ROOT_PASSWORD
作为容器环境?
如果我只输入 env_file
,MySQL 会启动,但会使用来自 ./mysql/.env
的凭据。它默默地忽略通过 --env-file
选项
提供的 .env 文件
最后,如果我同时输入 env_file
和 environment
,由于变量替换,它将遵循 --env-file
的值。但是执行到容器中并回显 $MYSQL_ROOT_PASSWORD
似乎很少丑陋,并且尖叫着等待发生的安全漏洞。
在我看来,我对 Docker Compose 环境变量的工作方式存在根本性的误解。
有人可以对这些问题做出某种澄清吗?
处理环境变量分为两个阶段:
- 在 Compose 级别,它采用自己的环境,并且还读取
docker-compose.yml
文件中的 docker compose --env-file
file, or if you don't specify that option, .env
. It then uses these environment variables to do variable substitution。
- 每个容器都有自己的环境,由 Compose
environment:
or env_file:
指令指定。
这意味着在外部环境中设置某些内容或将其放入 --env-file
文件(第 1 步)不会自动使其对容器可见(第 2 步)。
这与您的观察是一致的。在前两种情况下,指定 --env-file
不会在每个容器配置中放置任何内容,它只会影响环境变量扩展,因此从容器的角度来看它没有任何效果。在第三种情况下,您有正确的顺序:--env-file
在 Compose 级别设置变量,变量替换在 environment:
块中设置固定字符串,然后 environment:
takes precedence env_file:
.
我有一个 playground 项目 Docker 使用这样的文件编写:
version: '3'
services:
mysql:
image: 'mysql:8'
container_name: '${PROJECT_NAME}_mysql'
hostname: '${PROJECT_NAME}_mysql'
networks:
- internal
ports:
- '127.0.0.1:${MYSQL_EXPOSE_PORT}:3306'
volumes:
- mysql:/var/lib/mysql
env_file:
- ./mysql/.env
environment:
MYSQL_EXPOSE_PORT: '${MYSQL_EXPOSE_PORT}'
MYSQL_ROOT_PASSWORD: '${MYSQL_ROOT_PASSWORD}'
MYSQL_USER: '${MYSQL_USER}'
MYSQL_PASSWORD: '${MYSQL_PASSWORD}'
volumes:
mysql:
networks:
internal:
我的./mysql/.env
是这样的:
MYSQL_DATABASE=foobar
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=web
MYSQL_PASSWORD=web
我的 .env
文件如下所示:
COMPOSE_PROJECT_NAME=foobar
PROJECT_NAME=foobar
MYSQL_EXPOSE_PORT=33061
MYSQL_DATABASE=foobar
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=web_override
MYSQL_PASSWORD=web_override
我在某处读到 env_file
和 environment
创建的变量将在容器本身中可用,而 --env-file
提供在处理 [=20] 期间可用的变量=] 文件.
但是 运行 :
docker-compose -f docker-compose.yml --env-file .env up -d
对我来说,产生了意想不到的行为。
如果我同时省略
env_file
和environment
配置,MySQL 将因密码为空而无法启动。来自--env-file
的变量将被忽略。这是否意味着实际上需要MYSQL_ROOT_PASSWORD
作为容器环境?如果我只输入
提供的 .env 文件env_file
,MySQL 会启动,但会使用来自./mysql/.env
的凭据。它默默地忽略通过--env-file
选项最后,如果我同时输入
env_file
和environment
,由于变量替换,它将遵循--env-file
的值。但是执行到容器中并回显$MYSQL_ROOT_PASSWORD
似乎很少丑陋,并且尖叫着等待发生的安全漏洞。
在我看来,我对 Docker Compose 环境变量的工作方式存在根本性的误解。
有人可以对这些问题做出某种澄清吗?
处理环境变量分为两个阶段:
- 在 Compose 级别,它采用自己的环境,并且还读取
docker-compose.yml
文件中的docker compose --env-file
file, or if you don't specify that option,.env
. It then uses these environment variables to do variable substitution。 - 每个容器都有自己的环境,由 Compose
environment:
orenv_file:
指令指定。
这意味着在外部环境中设置某些内容或将其放入 --env-file
文件(第 1 步)不会自动使其对容器可见(第 2 步)。
这与您的观察是一致的。在前两种情况下,指定 --env-file
不会在每个容器配置中放置任何内容,它只会影响环境变量扩展,因此从容器的角度来看它没有任何效果。在第三种情况下,您有正确的顺序:--env-file
在 Compose 级别设置变量,变量替换在 environment:
块中设置固定字符串,然后 environment:
takes precedence env_file:
.