124

If I have a docker container that I started a while back, what is the best way to set an environment variable in that running container? I set an environment variable initially when I ran the run command.

$ docker run --name my-wordpress -e VIRTUAL_HOST=domain.example --link my-mysql:mysql -d spencercooley/wordpress

but now that it has been running for a while I want to add another VIRTUAL_HOST to the environment variable. I do not want to delete the container and then just re-run it with the environment variable that I want because then I would have to migrate the old volumes to the new container, it has theme files and uploads in it that I don't want to lose.

I would just like to change the value of VIRTUAL_HOST environment variable.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Spencer Cooley
  • 8,471
  • 16
  • 48
  • 63
  • 2
    It is not possible to change the environment variables of a running process except from within that process itself. This could be (made to be) possible by allowing to update the environment variable config (via `docker update) and then restarting the container. – cpuguy83 Jun 29 '16 at 13:33
  • I solve this problem with docker commit after some modifications in the base container, we only need to tag the new image https://docs.docker.com/engine/reference/commandline/commit/ – Jorge Tovar Dec 01 '20 at 22:18

17 Answers17

66

There are generaly two options, because docker doesn't support this feature now:

  1. Create your own script, which will act like runner for your command. For example:

    #!/bin/bash
    export VAR1=VAL1
    export VAR2=VAL2
    your_cmd
    
  2. Run your command following way:

    docker exec -i CONTAINER_ID /bin/bash -c "export VAR1=VAL1 && export VAR2=VAL2 && your_cmd"
    
mirek
  • 768
  • 5
  • 7
  • 37
    Now that it's been about 2.5 years, is this still the best way to do things or does docker allow a more direct approach? – Dean MacGregor Dec 05 '17 at 02:38
  • 4
    Try `docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR"` It outputs blank variable (expected `1`). What am I missing? – fabda01 Aug 16 '18 at 20:44
  • I believe these exports will have the accessible context till the execution of "your_cmd" only; for the access of these VARs in later sessions we need to put it into ~/.bashrc or .profile files , Kindly correct me if am wrong. – Ritesh Sharma Jan 21 '19 at 11:08
  • 6
    @yellow01 When you double quote variable references like in `"... echo $VAR"`, the variable is resolved in your current shell environment, which in this case is your Docker host. You can prove this out by trying `echo $HOSTNAME` for example, and the value will be your Docker host's hostname. Try single-quoting that command string to get your desired effect. – StockB Apr 03 '19 at 12:56
  • 2
    if you allow your container to be `restart` always, if this container has issue and restart automatically, what enviroment variables will be? – BMW Jun 29 '20 at 00:53
  • Can docker do something better now? – theonlygusti Apr 18 '23 at 15:34
28

Docker doesn't offer this feature.

There is an issue: "How to set an enviroment variable on an existing container? #8838"

Also from "Allow docker start to take environment variables #7561":

Right now Docker can't change the configuration of the container once it's created, and generally this is OK because it's trivial to create a new container.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Bryan
  • 11,398
  • 3
  • 53
  • 78
  • 2
    Ahh, that sucks. I will figure out a way. It is trivial to make a new container, but it is not trivial to take the volumes from an old container and mount them to a new container. I don't want to lose my wp-content directory. It really is not that hard to manually move over the volumes, but I am trying to automate things so it sort of defeats the purpose. Maybe I could write a python function that does this. https://gist.github.com/anonymous/68f4138261fdb73a6e79 – Spencer Cooley Jan 07 '15 at 16:55
  • 1
    Could you use a separate data-only container and `volumes-from` ? – Bryan Jan 08 '15 at 09:14
  • 3
    I am surprise 7 years later, Docker still doesn't imrpove this issue. – Cheung Jun 08 '22 at 07:33
20

For a somewhat narrow use case, docker issue 8838 mentions this sort-of-hack:

You just stop docker daemon and change container config in /var/lib/docker/containers/[container-id]/config.json (sic)

This solution updates the environment variables without the need to delete and re-run the container, having to migrate volumes and remembering parameters to run.

However, this requires a restart of the docker daemon. And, until issue issue 2658 is addressed, this includes a restart of all containers.

mknecht
  • 1,205
  • 11
  • 20
12

To:

  1. set up many env. vars in one step,
  2. prevent exposing them in 'sh' history, like with '-e' option (passing credentials/api tokens!),

you can use

--env-file key_value_file.txt

option:

docker run --env-file key_value_file.txt $INSTANCE_ID
MarKed
  • 167
  • 1
  • 7
10

Here's how you can modify a running container to update its environment variables. This assumes you're running on Linux. I tested it with Docker 19.03.8

Live Restore

First, ensure that your Docker daemon is set to leave containers running when it's shut down. Edit your /etc/docker/daemon.json, and add "live-restore": true as a top-level key.

sudo vim /etc/docker/daemon.json

My file looks like this:

{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    },
    "live-restore": true
}

Taken from here.

Get the Container ID

Save the ID of the container you want to edit for easier access to the files.

export CONTAINER_ID=`docker inspect --format="{{.Id}}" <YOUR CONTAINER NAME>`

Edit Container Configuration

Edit the configuration file, go to the "Env" section, and add your key.

sudo vim /var/lib/docker/containers/$CONTAINER_ID/config.v2.json

My file looks like this:

...,"Env":["TEST=1",...

Stop and Start Docker

I found that restarting Docker didn't work, I had to stop and then start Docker with two separate commands.

sudo systemctl stop docker
sudo systemctl start docker

Because of live-restore, your containers should stay up.

Verify That It Worked

docker exec <YOUR CONTAINER NAME> bash -c 'echo $TEST'

Single quotes are important here.

You can also verify that the uptime of your container hasn't changed:

docker ps
Ardan
  • 611
  • 7
  • 9
  • I am using linux ubuntu 20 with docker and couldn't find /etc/docker/daemon.json any tips? – Mark Odey Feb 05 '21 at 19:43
  • I think you can create it if it doesn't exist, but you could also check /var/snap/docker/current/config – Ardan Feb 08 '21 at 21:58
  • Docker container config locations under Windows WSL2: https://stackoverflow.com/questions/62380124/where-docker-image-is-stored-with-docker-desktop-for-windows – Vadzim Sep 26 '21 at 21:00
6

You wrote that you do not want to migrate the old volumes. So I assume either the Dockerfile that you used to build the spencercooley/wordpress image has VOLUMEs defined or you specified them on command line with the -v switch.

You could simply start a new container which imports the volumes from the old one with the --volumes-from switch like:

$ docker run --name my-new-wordpress --volumes-from my-wordpress -e VIRTUAL_HOST=domain.com --link my-mysql:mysql -d spencercooley/wordpres

So you will have a fresh container but you do not loose the old data. You do not even need to touch or migrate it.

A well-done container is always stateless. That means its process is supposed to add or modify only files on defined volumes. That can be verified with a simple docker diff <containerId> after the container ran a while.

In that case it is not dangerous when you re-create the container with the same parameters (in your case slightly modified ones). Assuming you create it from exactly the same image from which the old one was created and you re-use the same volumes with the above mentioned switch.

After the new container has started successfully and you verified that everything runs correctly you can delete the old wordpress container. The old volumes are then referred from the new container and will not be deleted.

Henrik Sachse
  • 51,228
  • 7
  • 46
  • 59
6

If you are running the container as a service using docker swarm, you can do:

docker service update --env-add <you environment variable> <service_name>

Also remove using --env-rm

To make sure it's addedd as you wanted, just run: docker exec -it <container id> env

Aaron_ab
  • 3,450
  • 3
  • 28
  • 42
4

1. Enter your running container:

sudo docker exec -it <container_name> /bin/bash

2. Run command to all available to user accessing the container and copy them to user running session that needs to run the commands:

printenv | grep -v "no_proxy" >> /etc/environment

3. Stop and Start the container

sudo docker stop <container_name>
sudo docker start <container_name>
Sergio Maziano
  • 489
  • 4
  • 6
3

here is how to update a docker container config permanently

  1. stop container: docker stop <container name>
  2. edit container config: docker run -it -v /var/lib/docker:/var/lib/docker alpine vi $(docker inspect --format='/var/lib/docker/containers/{{.Id}}/config.v2.json' <container name>)
  3. restart docker
Max Barrass
  • 2,776
  • 1
  • 19
  • 10
  • Where do I find this container config? – beruic Nov 04 '19 at 12:10
  • 1
    well if you are not on linux then container config is located in the VM that is running docker. This is why there is a volume mount to mount the volume from VM into a new container. Then this command would tell you where your particular container config is located $(docker inspect --format='/var/lib/docker/containers/{{.Id}}/config.v2.json' ) this is then passed to VI for you to edit. So my sample container config is /var/lib/docker/containers/55bf5a23a8bfb79ab80a56f3b92471f85009759925f95bb6522ca2041a43b5f8/config.v2.json – Max Barrass Feb 14 '20 at 10:08
  • 1
    you can read more about this on my blog entry https://aem.design/blog/2019/09/19/updating-existing-docker-container-variables%F0%9F%92%AA%F0%9F%98%8E%F0%9F%91%8D – Max Barrass Feb 14 '20 at 10:09
1

Firstly you can set env inside the container the same way as you do on a linux box.

Secondly, you can do it by modifying the config file of your docker container (/var/lib/docker/containers/xxxx/config.v2.json). Note you need restart docker service to take affect. This way you can change some other things like port mapping etc.

Leon
  • 3,124
  • 31
  • 36
  • 11
    it does not work. `config.v2.json`is generated. editing it does not change the container configuration. – Setop Oct 15 '19 at 21:52
0

I solve this problem with docker commit after some modifications in the base container, we only need to tag the new image and start that one

docs.docker.com/engine/reference/commandline/commit

docker commit [container-id] [tag]

docker commit b0e71de98cb9 stack-overflow:0.0.1

then you can pass environment vars or file

docker run --env AWS_ACCESS_KEY_ID --env AWS_SECRET_ACCESS_KEY --env AWS_SESSION_TOKEN --env-file env.local -p 8093:8093 stack-overflow:0.0.1

Jorge Tovar
  • 1,374
  • 12
  • 17
0

the quick working hack would be:

  1. get into the running container. docker exec -it <container_name> bash

  2. set env variable, install vim if not installed in the container

apt-get install vim

vi ~/.profile at the end of the file add export MAPPING_FILENAME=p_07302021

source ~/.profile check whether it has been set! echo $MAPPING_FILENAME(make sure you should come out of the container.)

  1. Now, you can run whatever you're running outside of the container from inside the container. Note, in case you're worried that you might lose your work if the current session you logged in gets logged off. you can always use screen even before starting step 1. That way if you logged off by chance of your inside running container session, you can log back in.
Anu
  • 3,198
  • 5
  • 28
  • 49
0

After understand that docker run an image constructed with a dockerfile , and the only way to change it is build another image stop everything and run everything again .

So the easy way to "set an environment variable in a running docker container" is read dockerfile [1] (with docker inspect) understand how docker starts [1]. In the example [1] we can see that docker start with /usr/local/bin/docker-php-entrypoint and we could edit it with vi and add one line with export myvar=myvalue since /usr/local/bin/docker-php-entrypoint Posix script .

If you can change dockerfile, you can add a call to a script [2] for example /usr/local/bin/mystart.sh and in that file we can set your environment var.
Of course after change the scripts you need restart the container [3]

[1]

$ docker inspect 011aa33ba92b
[{
  . . .
  "ContainerConfig": {
  "Cmd": [
      "php-fpm"
   ],
  "WorkingDir": "/app",
  "Entrypoint": [
   "docker-php-entrypoint"
 ],
    . . .
}]

[2]

/usr/local/bin/mystart.sh
#!/bin/bash
export VAR1=VAL1
export VAR2=VAL2
your_cmd

[3]

docker restart dev-php (container name)
Sérgio
  • 6,966
  • 1
  • 48
  • 53
-1

Hack with editing docker inner configs and then restarting docker daemon was unsuitable for my case.

There is a way to recreate container with new environment settings and use it for some time.

1. Create new image from runnning container:

docker commit my-service
a1b2c3d4e5f6032165497

Docker created new image, and answered with its id. Note, the image doesn't include mounts and networks.

2. Stop and rename original container:

docker stop my-service
docker rename my-service my-service-original

3. Create and start new container with modified environment:

docker run \
   -it --rm \
   --name my-service \
   --network=required-network \
   --mount type=bind,source=/host/path,target=/inside/path,readonly \
   --env 'MY_NEW_ENV_VAR=blablabla OLD_ENV=zzz' \
   a1b2c3d4e5f6032165497

Here, I did the following:

  • created new temporary container from image built on step 1, that will show its output on terminal, will exit on Ctrl+C, and will be deleted after that
  • configured its mounts and networks
  • added my custom environment configuration

4. After you worked with temporary container, press Ctrl+C to stop and remove it, and then return old container back:

docker rename my-service-original my-service 
docker start my-service
Eugene
  • 2,336
  • 21
  • 28
-2

How to set environment variable in a running docker container as a development environment

Basically you can do like in normal linux, adding export MY_VAR="value" to ~/.bashrc file.

Instructions

  1. Using VScode attach to your running container
  2. Then with VScode open the ~/.bashrc file
  3. Export your variable by adding the code in the end of the file
export MY_VAR="value"
  1. Finally execute .bashrc using source command
source ~/.bashrc
  • This won't affect the running process in the container. Even if you made this change in an image, it might not have an effect: most paths to running containers don't read `.bashrc` or other shell dotfiles. – David Maze Feb 02 '23 at 12:07
-5

You could set an environment variable to a running Docker container by

docker exec -it -e "your environment Key"="your new value" <container> /bin/bash

Verify it using below command

printenv

This will update your key with the new value provided.

Note: This will get reverted back to old on if docker gets restarted.

The_Black_Smurf
  • 5,178
  • 14
  • 52
  • 78
Goutham
  • 67
  • 4
  • 4
    This will open a bash shell with that environment variable set... it won't set it inside the existing container. The moment you exit that shell, even w/o restarting the container, you lose it. – user3534080 Nov 06 '19 at 19:45
  • Error response from daemon: No such container: your environment Key=your new value – Shōgun8 Mar 05 '20 at 22:27
-5

Use export VAR=Value

Then type printenv in terminal to validate it is set correctly.

Mark Han
  • 2,785
  • 2
  • 16
  • 31