Compose 里的环境变量有 .env、env_file、environment、shell、命令行好几个来源,谁覆盖谁?.env 里的变量会进容器吗?这篇设计了一组故意重名的变量,逐项量出结果。
compose.yaml 里的 environment 有 T_Y(引用 ${T_I})、T_Z、T_PASS(不写值);env_file 有 T_X、T_Y、T_I;.env 有 T_I=dotenv、T_ONLY_DOTENV=yes
默认:T_I=envfile-I T_X=from-envfile T_Y=environment-dotenv T_Z=environment容器里的变量:environment 覆盖 env_file;docker compose run -e 又覆盖前两者。
同时在 env_file 和 environment 里的 T_Y:取了 environment 的(上面的 T_Y 值);T_I 在 env_file 和 .env 里,容器里的 T_I 取自 env_file——.env 默认只用于 compose.yaml 里的插值,不进容器 .env 里独有的 T_ONLY_DOTENV 在容器里吗?不在 shell 里设 T_I=shell 后(插值优先级:shell 高于 .env):T_I=envfile-I T_X=from-envfile T_Y=environment-shell T_Z=environment T_PASS 不写值,shell 里设 T_PASS=from-shell:T_I=envfile-I T_PASS=from-shell T_X=from-envfile T_Y=environment-dotenv T_Z=environment docker compose run -e T_Z=cli -e T_X=cli:T_I=envfile-I T_X=cli T_Y=environment-dotenv T_Z=cli
.env 提供的是 compose.yaml 里 ${…} 插值用的变量,不会自动放进容器;而 env_file 的内容不参与插值(T_I 在 env_file 里是 envfile-I,插值仍用 .env 的 dotenv)。插值时 shell 的变量高于 .env,--env-file 可以换掉 .env。
--env-file other.env(T_I=other-env-file):T_I=envfile-I T_X=from-envfile T_Y=environment-other-env-file T_Z=environment
docker compose config 展开后的 environment:{'T_I': 'envfile-I', 'T_PASS': None, 'T_X': 'from-envfile', 'T_Y': 'environment-dotenv', 'T_Z': 'environment'}
--env-file other.env 之后展开的 environment:{'T_I': 'envfile-I', 'T_PASS': None, 'T_X': 'from-envfile', 'T_Y': 'environment-other-env-file', 'T_Z': 'environment'}environment 里只写变量名不写值,从运行 compose 的 shell 里取;shell 没设就不出现。
${T_MISSING:-default-value}-${T_EMPTY-unset} 在 T_MISSING 未设、T_EMPTY 未设时展开成:['echo', 'default-value-unset']
T_EMPTY 设成空串时(${T_EMPTY-unset} 只在未设置时用默认值):['echo', 'default-value-']
${T_REQUIRED:?…} 未设置时:退出码 1;error while interpolating services.web.command: required variable T_REQUIRED is missing a value: 必须设:- 对未设置或空串都用默认值;不带冒号的 - 只对未设置用默认值;:? 缺失时报错。env_file 与 image 的 ENV 的优先级关系我没有测。