Struggling to get a docker app to both pipe output to a file, and read input. Running the same command in bash works fine.
The command is a CLI I created called envwarden (a simple bash script wrapping around the Bitwarden CLI).
Easiest to show an example:
Running it locally (not inside docker), it works as expected:
$ ./envwarden --dotenv >/tmp/secrets.txt
.envwarden file not found in /home/user ... prompting for credentials
? Email address: [email protected]
? Master password: [hidden]
The prompts work fine. I can type in my email (shown), password (hidden), and the output goes to /tmp/secrets.txt
just fine.
With docker, things behave a bit differently.
With docker run -ti
(or just docker run -t
), there's no prompt at all for email or password...
$ docker run --rm -ti envwarden/envwarden envwarden --dotenv >/tmp/secrets.txt
# ... no output ...
With docker run -i
, the prompt shows, but anything I type is repeated, and password is shown as well! :-/
$ docker run --rm -i envwarden/envwarden envwarden --dotenv >/tmp/secrets.txt
.envwarden file not found in /root ... prompting for credentials
? Email address: [email protected]
? Email address: [email protected]
? Master password: [input is hidden] my password
? Master password: [hidden]
docker run
, without -t
or -i
it shows the prompt, but fails to get input
$ 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.
Here's the Dockerfile and docker-entrypoint.sh
How can I get docker to match the same behaviour as running locally? i.e. prompt for password without showing it, and redirect output to stdout.
The behavior you observe is due to the way docker run
handles standard streams.
In particular, this is related to moby/moby#725 and PR moby/moby#741:
If you pass no -i
nor -t
flag to docker run
: your terminal is not attached to the standard input of your main program, which thereby behaves as if you had typed empty strings as credentials.
If you only pass the -i
flag to docker run
, your terminal is attached to your program's stdin, but no pseudo-TTY is allocated, implying you get a not very user-friendly CLI interaction (no hiding feature during password typing, and possible duplication of output lines).
If you pass the -it
flags to docker run
: a pseudo-TTY is allocated, so the password prompt should work (hiding what you type), but at the same time, the stdout and stderr streams are mixed, so when you append the >/tmp/secrets.txt
redirection, you don't actually see the prompt as everything is sent to your /tmp/secrets.txt
file!
All in all, to achieve what you want I guess you should stick to the -it
option, but rather use a bash redirection "inside" the container (not outside) and also rely on some bind-mount option.
Hence the following proof of concept:
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"
(This should work normally, but I did not try it on your particular instance, so comments are welcome.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With