非交互式运行Docker容器无法回显环境变量的原因及bash验证方法
我正在编写说明文档,介绍基于Debian的Docker容器搭建方法。Debian默认将/bin/sh链接到dash shell,我希望展示在CMD中指定bash后,容器运行时会使用bash而非dash。
尝试通过回显$BASH_VERSION验证时,非交互式运行容器输出的是字面字符串$BASH_VERSION:
C:\Users\me>docker run --rm a6916e41aa87 echo "$BASH_VERSION" $BASH_VERSION
但交互式运行容器时,$BASH_VERSION能正常显示版本号:
C:\Users\me>docker run --rm -it a6916e41aa87 root@c4f60657c031:/# echo "$BASH_VERSION" 5.2.15(1)-release
容器镜像信息如下:
IMAGE CREATED CREATED BY SIZE COMMENT sha256:a6916e41aa871b09260f8949fe3c34570719f1c92ffe87d515b7eb702ebaebb1 2 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 2 weeks ago /bin/sh -c #(nop) ADD file:077a3156bd8271f26498ae6ac3800e68a42b9277581bc81eea31fec1a123dca5 in / 117MB
第一层是最小化Debian安装,第二层设置了CMD为bash。通过docker inspect查看环境变量:
C:\Users\me>docker inspect a6916e41aa87 --format "{{.Config.Env}}" [PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin]
即使回显$PATH也同样输出字面的$PATH,但普通字符串能正常回显:
C:\Users\me>docker run --rm -it a6916e41aa87 echo "hello world" hello world
请问:
- 为何非交互式运行时无法回显环境变量?
- 如何非交互式验证容器使用bash而非dash?
1. 非交互式运行无法回显环境变量的原因
当执行docker run --rm a6916e41aa87 echo "$BASH_VERSION"时,$BASH_VERSION是被本地Windows PowerShell解析的,而非容器内的bash。由于$BASH_VERSION不是PowerShell的环境变量,所以会被原样传递给容器内的bash,最终输出字面字符串。
此外,直接给docker run传命令参数时,Docker会将参数作为字符串传递给CMD指定的shell,不会触发shell的变量展开逻辑——除非显式让bash在子shell中执行命令。
2. 非交互式验证容器使用bash而非dash的方法
以下是几种可靠的验证方式:
方式一:让bash执行带变量展开的命令字符串
用bash -c参数让容器内的bash解析变量并执行命令:
docker run --rm a6916e41aa87 bash -c 'echo "$BASH_VERSION"'
输出示例:
5.2.15(1)-release
方式二:验证当前shell的进程名
通过查看进程链接目标或进程名称确认shell类型:
# 查看当前shell的可执行文件链接 docker run --rm a6916e41aa87 bash -c 'readlink /proc/self/exe'
输出示例(指向bash):
/bin/bash
或者用ps命令查看进程名:
docker run --rm a6916e41aa87 bash -c 'ps -p $$ -o comm='
输出示例:
bash
方式三:利用bash独有的语法特性
dash不支持bash的[[ ]]条件判断语法,执行成功则说明当前是bash:
docker run --rm a6916e41aa87 bash -c '[["test" == "test"]] && echo "Using bash"'
输出示例:
Using bash
如果是dash执行该命令,会抛出Syntax error: unexpected "["的错误。
内容的提问来源于stack exchange,提问作者Lorem Ipsum

