用环境变量传密码到底安全吗?这篇用一个假的秘密值,逐个检查 docker inspect、exec、/proc、日志、命令行和其它容器能不能看到它,以及 unset 之后的痕迹,最后对比挂载文件的做法。
docker inspect(Config.Env):能看到 docker inspect 整个输出:能看到 docker exec 里 env:能看到 容器里 /proc/1/environ:能看到 另一个容器(同一个网络)里 env:看不到 虚拟机里读 /proc/<容器主进程 PID>/environ:能看到 docker events / docker logs / docker ps:看不到 docker exec 起的后续进程继承环境变量:能看到
能运行 docker inspect 或 docker exec 的人可以直接读到环境变量,在虚拟机里也能从 /proc 读;没有权限的容器和日志里看不到。
docker ps --no-trunc 的 COMMAND 列(命令行里带 --token=…):能看到 docker top(命令行参数):能看到 docker inspect 的 Args / Path:能看到 docker events:看不到 容器还在运行吗?running
把秘密写在命令行参数里更糟,docker ps --no-trunc 就能列出来。
读到了,长度 21 os.environ 里还有吗: False /proc/self/environ 里还有吗: True docker exec cat /proc/1/environ(进程自己 pop 之后):能看到 docker inspect Config.Env(创建容器时的配置,与进程里是否 pop 无关):能看到
应用读完把变量 pop 掉只影响进程内的 os.environ;内核保留的启动时环境块(/proc/self/environ)和 docker 的配置都还在。
docker inspect 整个输出:看不到;docker exec env:看不到;/proc/1/environ:看不到 应用仍然读得到文件:能看到;docker inspect 里能看到文件的路径:True
只读挂载的秘密文件不出现在 docker inspect 的环境里,也不在 env 里;但仍然是「能进容器的人都能读」,所以它减少的是意外泄露面(日志、inspect 输出、环境转储),不是权限边界。BuildKit 的 secret mount(c8)是构建期的同类做法。运行期的专用方案(Swarm / Kubernetes secrets)我没有测。