Docker Compose -e参数无法覆盖.env中SCRIPT默认值问题
问题原因
你在docker-compose.yml的command字段中使用了${SCRIPT}语法,这个变量是Docker Compose解析配置文件阶段从本地.env或系统环境变量中读取的,属于静态替换,和容器运行时的环境变量无关。
当你执行docker-compose run -e SCRIPT=...时,只是给容器内部设置了环境变量,但command里的${SCRIPT}已经在Compose解析配置时被替换成了.env里的默认值,所以容器启动后还是执行原来的脚本。这也是为什么你用env命令能看到变量正确,但脚本不切换的原因——容器内变量确实存在,但command已经固定了。
解决方法
方法1:让command读取容器运行时环境变量
修改docker-compose.yml中的command字段,用shell执行命令,这样会在容器运行时解析环境变量:
services: app: # ... 其他配置不变 command: sh -c "python $SCRIPT"
修改后,执行docker-compose run --rm -e SCRIPT=tutorial_01/main.py app就能正常覆盖,因为$SCRIPT会在容器内部的shell中读取你传入的环境变量。
方法2:用Compose命令行变量覆盖解析阶段的值
如果想保持原有的command写法,可以在执行命令时直接设置Compose的环境变量,让解析阶段就替换成目标值:
SCRIPT=tutorial_01/main.py docker-compose run --rm app
这种方式下,Compose在解析command: python ${SCRIPT}时,会优先读取命令行设置的SCRIPT变量,生成的command就是python tutorial_01/main.py。
方法3:兼容两种变量替换方式
可以修改配置,同时支持Compose解析变量和容器运行时变量,兼顾默认值和动态覆盖:
services: app: # ... 其他配置不变 environment: - SCRIPT=${SCRIPT:-./tutorial_00/docker_test.py} command: sh -c "python $SCRIPT"
这个配置的效果:
- 未额外设置时,Compose会用
.env里的值设置容器的SCRIPT环境变量,执行默认脚本; - 用
docker-compose run -e SCRIPT=...可以直接覆盖容器内的环境变量,切换脚本; - 也可以用
SCRIPT=... docker-compose run ...的方式覆盖解析阶段的变量,同样生效。
内容的提问来源于stack exchange,提问作者Daniel

