dockerize 提示输入密码的 CLI

dockerize a CLI that prompts for password

努力获得一个 docker 应用程序来将输出管道输出到文件,并读取输入。 运行 bash 中的相同命令工作正常。

该命令是我创建的名为 envwarden (a simple bash script wrapping around the Bitwarden CLI) 的 CLI。

最简单的示例:

本地

运行 在本地(不在 docker 内),它按预期工作:

$ ./envwarden --dotenv >/tmp/secrets.txt
.envwarden file not found in /home/user ... prompting for credentials
? Email address: my@email.addr
? Master password: [hidden]

提示工作正常。我可以输入我的电子邮件(显示)、密码(隐藏),然后输出到 /tmp/secrets.txt 就好了。

和docker

对于 docker,情况会有所不同。

使用 docker run -ti(或只是 docker run -t),根本不会提示输入电子邮件或密码...

$ docker run --rm -ti envwarden/envwarden envwarden --dotenv >/tmp/secrets.txt

# ... no output ... 

使用 docker run -i 时,提示会显示,但我输入的任何内容都会重复,并且还会显示密码! :-/

$ docker run --rm -i envwarden/envwarden envwarden --dotenv >/tmp/secrets.txt
.envwarden file not found in /root ... prompting for credentials
? Email address: my@email.address
? Email address: my@email.address
? Master password: [input is hidden] my password
? Master password: [hidden]

docker run,没有-t-i显示提示,但输入失败

$ docker run --rm envwarden/envwarden envwarden --dotenv >/tmp/secrets.txt
.envwarden file not found in /root ... prompting for credentials
? Email address: unable to login or sync with bitwarden.

更多详情

这是Dockerfile and docker-entrypoint.sh

问题

如何让 docker 在本地匹配与 运行 相同的行为?即提示输入密码而不显示它,并将输出重定向到标准输出。

您观察到的行为是由于 docker run 处理标准流的方式所致。

特别是,这与moby/moby#725 and PR moby/moby#741有关:

  • 如果你没有将 -i-t 标志传递给 docker run:你的终端没有连接到你的主程序的标准输入,从而表现就好像您输入了空字符串作为凭据。

  • 如果你只将 -i 标志传递给 docker run,你的终端连接到你程序的标准输入,但没有分配伪 TTY,这意味着你没有非常用户友好的 CLI 交互(在输入密码时没有隐藏功能,并且输出行可能重复)。

  • 如果将 -it 标志传递给 docker run:分配伪 TTY,因此密码提示应该有效(隐藏您键入的内容),但在同时,stdout 和 stderr 流是混合的,所以当您附加 >/tmp/secrets.txt 重定向时,您实际上看不到提示,因为所有内容都发送到您的 /tmp/secrets.txt文件!

总而言之,为了实现你想要的,我想你应该坚持使用 -it 选项,而是使用 bash 重定向 "inside" 容器(而不是外部)和也依赖于一些绑定安装选项。

因此得出以下概念证明:

export out="/tmp/secrets.txt"  # absolute path to the output file in the host
docker run --rm -it -v "$out:$out" envwarden/envwarden \
  /bin/bash -c "envwarden --dotenv >$out"
cat "$out"

(这应该可以正常工作,但我没有在您的特定实例上尝试过,所以欢迎评论。)