225

What's the simplest way to get an environment variable from a docker container that has not been declared in the Dockerfile?

For instance, an environment variable that has been set through some docker exec container /bin/bash session?

I can do docker exec container env | grep ENV_VAR, but I would prefer something that just returns the value.

I've tried using docker exec container echo "$ENV_VAR", but the substitution seems to happen outside of the container, so I don't get the env var from the container, but rather the env var from my own computer.

Thanks.

Citronen
  • 4,050
  • 4
  • 16
  • 20

12 Answers12

261

To view all env variables:

docker exec container env

To get one:

docker exec container env | grep VARIABLE | cut -d'=' -f2
aisbaa
  • 9,867
  • 6
  • 33
  • 48
  • My question says that I'd prefer not to go that route. Also, follow-up question: `docker exec container env` and `docker exec -it container /bin/bash` and then `env` spit out different things. Why? – Citronen Dec 02 '15 at 19:58
  • Ah... might be the specific way I'm building the docker image that makes this the case... – Citronen Dec 02 '15 at 20:00
  • 3
    Hm, a lot harder now. Try `docker inspect container`. – aisbaa Dec 02 '15 at 20:01
  • `docker inspect container` seems to have the same limitation. If I create an environment variable after I run the container, it doesn't appear in a call to `docker inspect` (in the env section). – Citronen Dec 02 '15 at 20:25
  • I believe this is better answer than the currently accepted answer. We have several containers that are not supported with `bash` command, for example `alpine-node`. So using `exec container bash -c "echo $ENV_VAR"` aren't working. Using `exec container env` works for my case. Using `exec container printenv` also works. – Rahmat Nazali Salimi Jan 31 '20 at 07:07
  • 1
    Say @aisbaa if `VARIABLE` is a password generated from `openssl rand -base64 14` or any other case scenario where `VARIABLE` contains an equals sign then `cut -d'=' -f2` would leave out everything after the 2nd match, however, `cut -d '=' -f 2-` would only match the first delimiter and print everything after that. – Ava Barbilla Feb 10 '21 at 21:52
208

The proper way to run echo "$ENV_VAR" inside the container so that the variable substitution happens in the container is:

docker exec <container_id> bash -c 'echo "$ENV_VAR"'
Dan Woodward
  • 2,559
  • 1
  • 16
  • 19
jwodder
  • 54,758
  • 12
  • 108
  • 124
  • 13
    NOTICE that all these answers depend on some shell. I'm not able to get env variables with an executable and a scratch base image. – Richard Aug 02 '17 at 15:47
  • `docker run --rm -it CONTAINER bash -c 'echo "$MY_ENV_VAR"'` – Henrik Jan 14 '18 at 10:02
  • I am getting error "Error: No such container: container". I am executing command after login through SSH. – kunwar nitesh Apr 03 '19 at 14:21
  • 1
    @kunwarnitesh: You need to replace "container" with the name of the container you want to operate on. – jwodder Apr 03 '19 at 15:44
  • why does `docker exec echo $ENV_VAR` not work and we have to call `bash`? – Programer Beginner Jun 22 '20 at 00:03
  • See below an alternative with printenv which I would recommend since it does not depend on a shell and does not depend on quoting to keep the variable name intact. – jehon Oct 15 '21 at 08:54
113

You can use printenv VARIABLE instead of /bin/bash -c 'echo $VARIABLE. It's much simpler and it does not perform substitution:

docker exec container printenv VARIABLE
gentooboontoo
  • 4,653
  • 3
  • 20
  • 15
99

The downside of using docker exec is that it requires a running container, so docker inspect -f might be handy if you're unsure a container is running.

Example #1. Output a list of space-separated environment variables in the specified container:

docker inspect -f \
   '{{range $index, $value := .Config.Env}}{{$value}} {{end}}' container_name

the output will look like this:

ENV_VAR1=value1 ENV_VAR2=value2 ENV_VAR3=value3

Example #2. Output each env var on new line and grep the needed items, for example, the mysql container's settings could be retrieved like this:

docker inspect -f \
    '{{range $index, $value := .Config.Env}}{{println $value}}{{end}}' \
    container_name | grep MYSQL_

will output:

MYSQL_PASSWORD=secret
MYSQL_ROOT_PASSWORD=supersecret
MYSQL_USER=demo
MYSQL_DATABASE=demodb
MYSQL_MAJOR=5.5
MYSQL_VERSION=5.5.52

Example #3. Let's modify the example above to get a bash friendly output which can be directly used in your scripts:

docker inspect -f \
   '{{range $index, $value := .Config.Env}}export {{$value}}{{println}}{{end}}' \
   container_name | grep MYSQL

will output:

export MYSQL_PASSWORD=secret
export MYSQL_ROOT_PASSWORD=supersecret
export MYSQL_USER=demo
export MYSQL_DATABASE=demodb
export MYSQL_MAJOR=5.5
export MYSQL_VERSION=5.5.52

If you want to dive deeper, then go to Go’s text/template package documentation with all the details of the format.

Sergiy Sokolenko
  • 5,967
  • 35
  • 37
  • 2
    that's the best answer. I think is should be the answer on a separate question (when container is down) – Nickolay Kondratenko Mar 12 '18 at 19:01
  • This is the only answer that worked for me. `docker exec` always said my container is not know. – Good Night Nerd Pride Sep 30 '19 at 10:59
  • 2
    This is the best answer because every other solution uses `docker exec` which depends on having whatever command you `exec` to be supported by the container. This answer on the other hand works for any container since it only relies on the container metadata. – Kris Sep 08 '20 at 18:25
  • 1
    could you explain why `$index`? I read https://golang.org/pkg/text/template/ but still don't understand why using two variables when only one is used. – Stefan Sep 13 '20 at 18:49
  • @Stefan, you're right, the `$index` is unused in the code example and we could omit it. To be honest, I simply overlooked it at the time of writing, but now I'd leave it for a better overview of the syntax. As an example where we could still use the `$index` variable (naming it as `$key`) would be something like this `{{range $key, $value := .State}}`. – Sergiy Sokolenko Sep 14 '20 at 06:44
  • thx for the reply but I don't get your example, sorry :(. $key is not used. – Stefan Sep 15 '20 at 20:17
  • 2
    @Stefan, full example will look like this: `{{range $key, $value := .State}}{{$key}}="{{$value}}"{{println}}{{end}}`. – Sergiy Sokolenko Sep 22 '20 at 08:36
19

Since we are dealing with JSON and unlike the accepted answer, we don't need to exec the container.

docker inspect <NAME|ID> | jq '.[] | .Config.Env'

Output sample

[
  "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  "NGINX_VERSION=1.19.4",
  "NJS_VERSION=0.4.4",
  "PKG_RELEASE=1~buster"
]

To retrieve a specific variable

docker inspect <NAME|ID> | jq -r '.[].Config.Env[]|select(match("^<VAR_NAME>"))|.[index("=")+1:]'

See jq

Alex Nolasco
  • 18,750
  • 9
  • 86
  • 81
11

None of the above answers show you how to extract a variable from a non-running container (if you use the echo approach with run, you won't get any output).

Simply run with printenv, like so:

docker run --rm <container> printenv <MY_VAR>

(Note that docker-compose instead of docker works too)

Kabir Sarin
  • 18,092
  • 10
  • 50
  • 41
5

If by any chance you use VSCode and has installed the docker extension, just right+click on the docker you want to check (within the docker extension), click on Inspect, and there search for env, you will find all your env variables values

ddieppa
  • 5,866
  • 7
  • 30
  • 40
1

We can modify entrypoint of a non-running container with the docker run command.

Example show PATH environment variable:

  1. using bash and echo: This answer claims that echo will not produce any output, which is incorrect.

    docker run --rm --entrypoint bash <container> -c 'echo "$PATH"'
    
  2. using printenv

    docker run --rm --entrypoint printenv <container> PATH
    
Sathish
  • 12,453
  • 3
  • 41
  • 59
0

@aisbaa's answer works if you don't care when the environment variable was declared. If you want the environment variable, even if it has been declared inside of an exec /bin/bash session, use something like:

IFS="=" read -a out <<< $(docker exec container /bin/bash -c "env | grep ENV_VAR" 2>&1)

It's not very pretty, but it gets the job done.

To then get the value, use:

echo ${out[1]}
Citronen
  • 4,050
  • 4
  • 16
  • 20
0

This command inspects docker stack processes' environment in the host :

pidof   dockerd containerd containerd-shim | tr ' ' '\n' \
      | xargs -L1 -I{} -- sudo xargs -a '/proc/{}/environ' -L1 -0
MatteoOreficeIT
  • 190
  • 2
  • 5
0

The first way we use to find the ENV variables is docker inspect <container name>

The second way is docker exec <4 alphanumeric letter of CONTAINER id> bash -c 'echo "$ENV_VAR"'

yuviscor
  • 31
  • 3
0

There is a misconception in the question, that causes confusion:

you cannot access a "running session", so no bash session can change anything.

docker exec -ti container /bin/bash

starts a new console process in the container, so if you do export VAR=VALUE this will go away as soon as you leave the shell, and it won't exist anymore.

Perhaps a good example:

# assuming TESTVAR did not existed previously this is empty 
docker exec container env | grep TESTVAR

# -> TESTVAR=a new value!
docker exec container /bin/bash -c 'TESTVAR="a new value!" env' | grep TESTVAR

# again empty
docker exec container env | grep TESTVAR

The variables from env come from the Dockerfile or command, docker itself and whatever the entrypoint sets.

The other answers here are good. But if you really need to get the environmental properties used when starting a program, then you can inspect the /proc/pid/environ contents in the container, where pid is the container process id of the running comand.

# environmental props 
docker exec container cat /proc/pid/environ | tr '\0' '\n'

# you can check this is the correct pid by checking the ran command
docker exec container cat /proc/pid/cmdline | tr '\0' ' '
estani
  • 24,254
  • 2
  • 93
  • 76