45

Using docker run with a bunch of -e flags or even a .env seems cumbersome.

Is there any simply way to just pass all of the host env variables to a docker container

user1686342
  • 1,265
  • 1
  • 18
  • 24
  • 1
    This is probably a terrible idea. What's the use case? – johnharris85 Oct 24 '16 at 23:39
  • Not having to create an additional file to manage config and therefore update everyone a new env var is required – user1686342 Oct 24 '16 at 23:44
  • 1
    Can you elaborate anymore? If you have that much (dynamic?) configuration maybe look at something like consul / consul-template etc...? – johnharris85 Oct 25 '16 at 01:20
  • For me the use case is for local runs. I have a make target which does `docker run foo` and it is for local testing. It is cumbersome to keep the make target up to date with the production Kubernetes configmap, and just forwarding everything to the container seems like a quick workaround. – Jan Steinke Feb 04 '21 at 08:18

5 Answers5

47

I agree with the commenters who have suggested that you may not actually want to do what you think you want to do. However:

If (a) you're interested in environment variables with a specific prefix and (b) your variables don't contain any whitespace, something like this would work...here, I'm exposing all the XDG_* variables to a docker container:

$ docker run -it --rm --env-file <(env | grep XDG) alpine sh
/ # env | grep XDG
XDG_SEAT=seat0
XDG_SESSION_TYPE=x11
XDG_SESSION_ID=2
XDG_RUNTIME_DIR=/run/user/21937
XDG_MENU_PREFIX=gnome-
XDG_CURRENT_DESKTOP=GNOME
XDG_SESSION_DESKTOP=gnome
XDG_VTNR=2

If you really want all environment variables, you would probably need to write a smaller wrapper program that would produce properly quoted output (to handle variables that contain whitespace), and that would exclude things that span multiple lines, like the BASH_FUNC_* variables. Then you would use your wrapper in place of the env | grep ... in the previous example.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • 1
    Is specifying an env file the best practice to follow? – user1686342 Oct 25 '16 at 12:57
  • I'm not sure exactly how to answer that question, since I really don't know your use case. If you have a large number of environment variables that are required to configure the container, an environment file seems like a good idea to me (vs. putting them all on the command line). Or using docker compose to do something similar. But it's also possible that if you are designing your own images that maybe there is a better way of getting any necessary configuration into the container rather than using environment variables. – larsks Oct 25 '16 at 13:05
  • Thank you for taking the time to answer the question, even if this style of doing things is not 'correct'. This answer has allowed me to run `docker-compose` inside of a container while maintaining the ability to use environment variable injection in my compose file: `MY_VAR=derp docker-compose up` – Ben Behar Sep 29 '17 at 05:21
  • Does the special input redirection for the env file work across OSes? I'm assuming this is for Linux. Doesn't seem to work on Mac. Wonder how it would be done on Windows. – David Nov 01 '18 at 00:45
  • There is no "special input redirection" happening here. The `<(...)` is standard Bash syntax; it runs the process list inside the `(...)` and replaces the expression with a filename that is connected to the output of that process list. It should be supported in at least anything later than bash 3.0 (and possibly earlier). That suggests that it ought to work fine on MacOS. If things aren't working as expected, you may want to open a new question on that topic. – larsks Nov 01 '18 at 01:54
18

There are two ways to use the -e flag: -e VAR=VALUE and -e VAR; if VAR is already exported then the second format will use the exported value without making it publicly readable, plus you don't need to worry about escaping the VALUE against whitespace, quotes, etc.

So if you really want to pass in all exported variables to your container, try this:

docker run ... $(env | cut -f1 -d= | sed 's/^/-e /') ...
user3324033
  • 309
  • 2
  • 4
  • Does the env parameter substitution/injection here work across OSes? I'm assuming this is for Linux. Doesn't seem to work on Mac, or maybe I don't have exported variables to use in my case. Wonder how it would be done on Windows. – David Nov 01 '18 at 00:45
11

Mixing a bit of both answer for @user3324033 and @larsks, here is what worked best for me to get all exported environment variables and mimic Apptainer/Singularity behaviors:

docker run [...] --env-file <( env| cut -f1 -d= ) [...]
Blaa_Thor
  • 584
  • 6
  • 13
  • Does the special input redirection for the env file work across OSes? I'm assuming this is for Linux. Doesn't seem to work on Mac. Wonder how it would be done on Windows. – David Nov 01 '18 at 00:45
  • it depends on your version of bash. I think OSX has 3.X.X and linux is now 4.X.X – Blaa_Thor Aug 23 '19 at 16:51
2

I found @larsks's answer very enlightening, but found I needed to be a little more surgical in how I injected variables into my containers.

If you utilize Makefiles for your container building and/or running, you can combine gnu make's foreach keyword with env -i to easily inject environment variables into your container:

SHELL := /bin/bash

FOO := myfooenv
BAR := mybarenv

VARS := FOO BAR

run:
    docker run --rm -it \
        --env-file <(env -i $(foreach var,$(VARS),$(var)=$($(var)))) \
        bash:latest \
        bash -c ' \
            set -e; \
            env; \
        '

Which would give the output:

$ make run
docker run --rm -it \
        --env-file <(env -i FOO=myfooenv BAR=mybarenv) \
        bash:latest \
        bash -c ' \
            set -e; \
            env; \
        '
HOSTNAME=9d3b6863b8f2
_BASH_VERSION=4.4
_BASH_LATEST_PATCH=23
PWD=/
HOME=/root
FOO=myfooenv
_BASH_GPG_KEY=7C0135FB088AAF6C66C650B9BB5869F064EA74AB
TERM=xterm
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
BAR=mybarenv
_BASH_PATCH_LEVEL=18
_=/usr/bin/env
Levi Noecker
  • 3,142
  • 1
  • 15
  • 30
1

Probably the least ideal answer in terms of security here, but if all else fails, I resorted to something like this that worked for me:

env > env.txt; docker run -it [...] --env-file env.txt [...]; rm env.txt

for above assuming you're running it as an interactive session. Be different to handle cleanup of env.txt if you're running it as a service in the background.

One could set RW permissions on the file within the command chain perhaps to make it more secure. And switch ; to && for better dependent execution of the commands

I myself tried the other solutions with no luck (I'm on Mac OS, using bash 4 via brew if that makes a difference).

David
  • 3,223
  • 3
  • 29
  • 41