如何在docker-entrypoint.sh中动态设置环境变量?
问题
我有一个Go二进制程序,运行后会输出如下格式的环境变量导出语句:
export FOO="BAR" export BAZ="QUX"
我编写了docker-entrypoint.sh脚本,通过eval执行这些输出语句来设置环境变量,脚本内容如下:
#!/bin/bash set -e ssm_available() { if [ -z "$SSM_BASE_PATH" ]; then return 1 fi return 0 } export_ssm_params_go() { set -x eval $(./ssm_get_parameter --path ${SSM_BASE_PATH}) exec "$@" } main() { if ssm_available; then echo "Info: Loading SSM Parameters" >&2 export_ssm_params_go "$@" fi echo "Info: Starting ..." >&2 exec "$@" } main "$@"
Dockerfile末尾配置如下:
... ENTRYPOINT [ "sh", "docker-entrypoint.sh" ] CMD ["node", "server.js"]
脚本执行成功,日志显示变量已被导出:
Info: Loading SSM Parameters + ./ssm_get_parameter --path /p-stack-fs/env/production + eval export 'FOO="TEST"' + export 'FOO=TEST' + exec node server.js
实际程序可以正常使用这些动态设置的环境变量,但通过docker exec进入容器执行env命令时,却看不到这些变量,只有Dockerfile中用ENV定义的变量能正常显示,请问这是什么原因?
解答
核心原因:进程环境变量的独立性
动态变量仅存在于容器主进程的空间中
你通过eval设置的环境变量,首先是在docker-entrypoint.sh所在的shell进程中生效;随后脚本执行exec node server.js,这个命令会直接替换当前的shell进程为node进程,node进程会完全继承shell进程的环境变量,所以你的应用程序能正常读取到这些变量。docker exec启动的是全新独立进程docker exec的本质是在容器内创建一个全新的进程(默认是shell),这个进程的环境变量来源于容器启动时的初始环境——也就是Dockerfile里ENV定义的变量、docker run命令通过-e传入的变量,不会继承容器主进程(node)后续动态添加的环境变量。这就是为什么你用docker exec查不到这些变量,但应用本身能正常使用它们的原因。
内容的提问来源于stack exchange,提问作者PGT
相关产品推荐
相关产品推荐

