如何在运行中的Docker容器中设置环境变量

128

如果我有一个一段时间前启动的Docker容器,如何最好地在运行中的容器中设置环境变量?我在运行run命令时最初设置了一个环境变量。

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

但现在它已经运行一段时间了,我想将另一个VIRTUAL_HOST添加到环境变量中。我不想删除容器,然后只是使用我想要的环境变量重新运行它,因为那样我就必须将旧卷迁移到新容器中,里面有主题文件和上传文件,我不想丢失它们。

我只想更改VIRTUAL_HOST环境变量的值。


2
除非在进程内部更改,否则无法更改正在运行的进程的环境变量。这可以通过允许更新环境变量配置(通过docker update),然后重新启动容器来实现。 - cpuguy83
我在基础容器中进行了一些修改后,使用docker commit解决了这个问题,我们只需要为新镜像打标签。https://docs.docker.com/engine/reference/commandline/commit/ - Jorge Tovar
17个回答

68

一般有两个选项,因为docker现在不支持这个功能:

  1. 创建自己的脚本,可以像命令运行器一样运行你的命令。例如:

    #!/bin/bash
    export VAR1=VAL1
    export VAR2=VAL2
    your_cmd
    
  2. 按以下方式运行您的命令:

    docker exec -i CONTAINER_ID /bin/bash -c "export VAR1=VAL1 && export VAR2=VAL2 && your_cmd"
    

41
现在已经过去了约2.5年,这仍然是最佳方法吗?还是Docker提供了更直接的方法? - Dean MacGregor
4
尝试执行 docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR",输出的结果是空白变量(预期为 1)。我错过了什么? - fabda01
我相信这些导出变量只有在执行“your_cmd”时才有可访问的上下文;如果要在以后的会话中访问这些VAR,我们需要将其放入~/.bashrc或.profile文件中,请纠正我如果我错了。 - Ritesh Sharma
7
当你在 "... echo $VAR" 中双引用变量引用时,该变量会在当前的 shell 环境中解析,该环境在本例中是你的 Docker 主机。你可以通过尝试 echo $HOSTNAME 来证明这一点,该值将是你的 Docker 主机的主机名。尝试单引用该命令字符串以获得你想要的效果。 - StockB
3
如果您允许容器始终“重启”,如果此容器出现问题并自动重启,那么会有哪些环境变量? - BMW
1
现在Docker能做得更好吗? - theonlygusti

29

2
啊,那太糟糕了。我会想出一个办法的。创建一个新容器很简单,但是将旧容器的卷挂载到新容器上并不容易。我不想失去我的wp-content目录。手动移动卷其实并不难,但我正在尝试自动化这些事情,所以这有点违背初衷。也许我可以编写一个Python函数来完成这个任务。 https://gist.github.com/anonymous/68f4138261fdb73a6e79 - Spencer Cooley
1
你可以使用一个单独的数据容器和 volumes-from 吗? - Bryan
3
我很惊讶,7年后Docker仍未解决这个问题。 - Cheung

20

针对一个相对狭窄的用例,docker issue 8838提到了一个类似于hack的解决方案:

您只需停止docker守护进程并更改位于 /var/lib/docker/containers/[container-id]/config.json (sic) 中的容器配置即可。

此解决方案更新环境变量,而不需要删除和重新运行容器,避免了迁移卷和记住运行参数。

但是,这需要重新启动docker守护程序。并且,在问题 issue 2658 得到解决之前,这包括重新启动所有容器


12

To:

  1. 一步设置多个环境变量,
  2. 避免在“sh”历史记录中暴露它们,例如使用“-e”选项(传递凭据/ API令牌!)

您可以使用

--env-file key_value_file.txt

选项:

docker run --env-file key_value_file.txt $INSTANCE_ID

9
您的陈述缺乏背景信息,无法理解其意义。 - Sérgio
2
在一个(已经)运行的Docker容器中 - undefined

10

以下是如何修改正在运行的容器以更新其环境变量的方法。假设您在Linux上运行。我使用Docker 19.03.8进行了测试。

实时还原

首先,请确保您的Docker守护程序设置为在关闭时保留容器运行状态。编辑您的/etc/docker/daemon.json文件,并将"live-restore": true添加为顶级键。

sudo vim /etc/docker/daemon.json

我的文件看起来像这样:

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

本内容摘自此处

获取容器ID

保存要编辑的容器的ID以便更轻松地访问文件。

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

编辑容器配置

编辑配置文件,前往“Env”部分并添加您的密钥。

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

我的文件看起来像这样:

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

停止和启动Docker

我发现重新启动Docker不起作用,我必须使用两个单独的命令停止然后启动Docker。

sudo systemctl stop docker
sudo systemctl start docker

由于live-restore功能,您的容器应该保持运行状态。

验证是否生效

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

这里单引号很重要。

您还可以验证容器的正常运行时间是否发生了变化:

docker ps

我正在使用带有Docker的Linux Ubuntu 20,但找不到/etc/docker/daemon.json文件,有什么提示吗? - Mark Odey
如果不存在,我认为你可以创建它,但你也可以检查 /var/snap/docker/current/config。 - Ardan
Windows WSL2下Docker容器的配置位置:https://dev59.com/DlIG5IYBdhLWcg3w42Bn - Vadzim

6

如果您正在使用docker swarmservice的形式运行容器,则可以执行以下操作:

docker service update --env-add <您的环境变量> <服务名称>

要删除环境变量,请使用--env-rm标志

要确保它按您的要求添加,请运行: docker exec -it <容器ID> env


6

你写道你不想迁移旧的卷。因此我假设你用于构建 spencercooley/wordpress 镜像的 Dockerfile 定义了 VOLUME,或者你在命令行上使用 -v 开关指定了这些内容。

你可以简单地启动一个新容器,并使用 --volumes-from 开关从旧容器中导入卷,如下所示:

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

所以你将拥有一个新的容器,但不会丢失旧数据。你甚至不需要触碰或迁移它。一个良好的容器总是无状态的。这意味着它的进程只应添加或修改定义卷上的文件。在容器运行一段时间后,可以使用简单的docker diff <containerId>进行验证。在这种情况下,当您使用相同的参数重新创建容器(在您的情况下略微修改)时,这并不危险。假设您从与旧容器创建相同的镜像创建它,并重复使用具有上述开关的相同卷。新容器成功启动并验证一切正常后,您可以删除旧的WordPress容器。然后,新容器将引用旧卷,并且旧卷不会被删除。

4

1. 进入运行中的容器:

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

2. 运行命令以使所有可以访问容器的用户将其复制到需要运行命令的用户会话中:

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

3. 停止和启动容器

sudo docker stop <container_name>
sudo docker start <container_name>

3

以下是如何永久更新docker容器配置的步骤:

  1. 停止容器:docker stop <container name>
  2. 编辑容器配置: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. 重新启动docker

我在哪里找到这个容器配置? - beruic
1
如果您不在Linux上,则容器配置位于运行Docker的虚拟机中。这就是为什么有一个卷挂载将VM中的卷挂载到新容器中。然后,此命令将告诉您特定容器配置位于何处$(docker inspect --format='/var/lib/docker/containers/{{.Id}}/config.v2.json' <container name>),然后将其传递给VI进行编辑。因此,我的示例容器配置为/var/lib/docker/containers/55bf5a23a8bfb79ab80a56f3b92471f85009759925f95bb6522ca2041a43b5f8/config.v2.json。 - Max Barrass
1
您可以在我的博客文章中了解更多信息: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

1
首先,您可以在容器内设置环境变量,方式与在Linux上相同。
其次,您可以通过修改docker容器的配置文件(/var/lib/docker/containers/xxxx/config.v2.json)来实现。请注意,您需要重新启动docker服务才能生效。这种方法还可以更改其他一些内容,如端口映射等。

11
无法正常工作。生成了config.v2.json文件。编辑它不会改变容器的配置。 - Setop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接