【问题标题】:How to set an environment variable in a running docker container如何在正在运行的 docker 容器中设置环境变量
【发布时间】:2015-03-04 22:33:23
【问题描述】:

如果我有一个不久前启动的 docker 容器,那么在该运行容器中设置环境变量的最佳方法是什么?我最初在运行运行命令时设置了一个环境变量。

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

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

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

【问题讨论】:

  • 无法更改正在运行的进程的环境变量,除非从该进程本身内部更改。这可以通过允许更新环境变量配置(通过`docker update)然后重新启动容器来实现。
  • 我在基础容器中做了一些修改后用docker commit解决了这个问题,我们只需要标记新的镜像docs.docker.com/engine/reference/commandline/commit

标签: docker


【解决方案1】:

一般有两种选择,因为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"
    

【讨论】:

  • 现在已经过去了大约 2.5 年,这仍然是最好的做事方式还是 docker 允许更直接的方法?
  • 尝试docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR" 它输出空白变量(预期1)。我错过了什么?
  • 我相信这些导出将具有可访问的上下文,直到执行“your_cmd”为止;为了在以后的会话中访问这些 VAR,我们需要将其放入 ~/.bashrc 或 .profile 文件中,如果有错误请纠正我。
  • @yellow01 当您像"... echo $VAR" 那样对变量引用进行双引号时,该变量将在您当前的shell 环境中解析,在本例中是您的Docker 主机。例如,您可以通过尝试echo $HOSTNAME 来证明这一点,该值将是您的 Docker 主机的主机名。尝试单引号该命令字符串以获得您想要的效果。
  • 如果你允许你的容器总是restart,如果这个容器有问题并自动重启,环境变量会是什么?
【解决方案2】:

Docker 不提供此功能。

有一个问题:“How to set an enviroment variable on an existing container? #8838

也来自“Allow docker start to take environment variables #7561”:

目前 Docker 无法在创建容器后更改其配置,通常这是可以的,因为创建新容器很简单。

【讨论】:

  • 啊,太糟糕了。我会想办法的。制作一个新容器很简单,但从旧容器中取出卷并将它们安装到新容器中并非易事。我不想丢失我的 wp-content 目录。手动移动卷确实并不难,但我正在尝试使事情自动化,所以它有点违背了目的。也许我可以编写一个 python 函数来做到这一点。 gist.github.com/anonymous/68f4138261fdb73a6e79
  • 您可以使用单独的纯数据容器和volumes-from 吗?
【解决方案3】:

对于一个有点狭窄的用例,docker issue 8838 提到了这种黑客攻击:

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

此解决方案无需删除并重新运行容器即可更新环境变量,无需迁移卷并记住参数到run

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

【讨论】:

    【解决方案4】:

    收件人:

    1. 设置多个环境。 vars 一步到位,
    2. 防止将它们暴露在“sh”历史记录中,例如使用“-e”选项(传递凭据/api 令牌!),

    你可以使用

    --env-file key_value_file.txt

    选项:

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

    【讨论】:

    • 你的陈述完全断章取义
    【解决方案5】:

    以下是修改正在运行的容器以更新其环境变量的方法。这假设您在 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
    }
    

    取自here

    获取容器 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 任何提示?
    • 我认为如果它不存在你可以创建它,但你也可以检查 /var/snap/docker/current/config
    • Windows WSL2 下的 Docker 容器配置位置:stackoverflow.com/questions/62380124/…
    【解决方案6】:

    您写道您不想迁移旧卷。因此,我假设您用于构建spencercooley/wordpress 映像的Dockerfile 定义了VOLUMEs,或者您在命令行中使用-v 开关指定了它们。

    您可以简单地启动一个新容器,该容器使用 --volumes-from switch 从旧容器导入卷,例如:

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

    因此,您将拥有一个新容器,但不会丢失旧数据。 您甚至不需要触摸或迁移它

    做得好的容器总是无状态的。这意味着它的过程应该只添加或修改已定义卷上的文件。这可以在容器运行一段时间后通过简单的docker diff &lt;containerId&gt; 进行验证。

    在这种情况下,使用相同的参数(在您的情况下稍作修改)重新创建容器并不危险。假设您从创建旧映像的完全相同的映像创建它,并且您通过上述开关重新使用相同的卷。

    在新容器成功启动并且您验证一切正常运行后,您可以删除旧的 wordpress 容器。然后从新容器中引用旧卷并且不会被删除。

    【讨论】:

      【解决方案7】:

      如果您使用docker swarm 将容器作为service 运行,您可以这样做:

      docker service update --env-add &lt;you environment variable&gt; &lt;service_name&gt;

      也可以使用--env-rm 删除

      要确保它按您的需要添加,只需运行: docker exec -it &lt;container id&gt; env

      【讨论】:

        【解决方案8】:

        首先,您可以像在 linux 机器上一样在容器内设置 env。

        其次,您可以通过修改 docker 容器的配置文件 (/var/lib/docker/containers/xxxx/config.v2.json) 来实现。请注意,您需要重新启动 docker 服务才能生效。这样你就可以改变一些其他的东西,比如端口映射等。

        【讨论】:

        • 它不起作用。生成config.v2.json。编辑它不会更改容器配置。
        【解决方案9】:

        这里是如何永久更新 docker 容器配置

        1. 停止容器:docker stop &lt;container name&gt;
        2. 编辑容器配置:docker run -it -v /var/lib/docker:/var/lib/docker alpine vi $(docker inspect --format='/var/lib/docker/containers/{{.Id}}/config.v2.json' &lt;container name&gt;)
        3. 重启泊坞窗

        【讨论】:

        • 在哪里可以找到这个容器配置?
        • 好吧,如果您不在 linux 上,那么容器配置位于运行 docker 的 VM 中。这就是为什么要使用卷挂载将卷从 VM 挂载到新容器中的原因。然后这个命令会告诉你你的特定容器配置在哪里 $(docker inspect --format='/var/lib/docker/containers/{{.Id}}/config.v2.json' ) 这个然后传递给 VI 供您编辑。所以我的示例容器配置是 /var/lib/docker/containers/55bf5a23a8bfb79ab80a56f3b92471f85009759925f95bb6522ca2041a43b5f8/config.v2.json
        • 您可以在我的博客条目aem.design/blog/2019/09/19/…中阅读更多相关信息
        【解决方案10】:

        我用 docker commit 在基础容器中进行了一些修改后解决了这个问题,我们只需要标记新图像并启动那个

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

        docker 提交 [container-id] [tag]

        docker commit b0e71de98cb9 stack-overflow:0.0.1

        然后你可以传递环境变量或文件

        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

        【讨论】:

          【解决方案11】:

          快速工作的技巧是:

          1. 进入正在运行的容器。 docker exec -it &lt;container_name&gt; bash

          2. set env variable, 如果容器中没有安装 vim,请安装 vim

          apt-get install vim

          vi ~/.profile在文件末尾添加export MAPPING_FILENAME=p_07302021

          source ~/.profile 检查是否已设置! echo $MAPPING_FILENAME(确保你应该从容器中出来。)

          1. 现在,您可以从容器内部运行在容器外部运行的任何内容。 请注意,如果您担心如果您登录的当前会话被注销,您可能会丢失您的工作。即使在开始第 1 步之前,您也可以随时使用screen。这样,如果您在内部运行的容器会话中退出,您可以重新登录。

          【讨论】:

            【解决方案12】:

            在了解 docker run 一个使用 dockerfile 构建的镜像后,改变它的唯一方法是构建另一个镜像,停止一切并再次运行一切。

            因此,“在正在运行的 docker 容器中设置环境变量”的简单方法是读取 dockerfile [1](使用 docker inspect)了解 docker 如何启动 [1]。 在示例 [1] 中,我们可以看到 docker 以 /usr/local/bin/docker-php-entrypoint 开头,我们可以使用 vi 对其进行编辑并添加一行 export myvar=myvalue,因为 /usr/local/bin/docker-php-entrypoint Posix 脚本。

            如果您可以更改 dockerfile,您可以添加对脚本 [2] 的调用,例如 /usr/local/bin/mystart.sh,我们可以在该文件中设置您的环境变量。
            当然,更改脚本后,您需要重新启动容器 [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)
            

            【讨论】:

              【解决方案13】:

              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>
              

              【讨论】:

                【解决方案14】:

                您可以通过

                将环境变量设置为正在运行的 Docker 容器

                docker exec -it -e "your environment Key"="your new value" &lt;container&gt; /bin/bash

                使用以下命令验证它

                printenv

                这将使用提供的新值更新您的密钥。

                注意:如果 docker 重新启动,这将恢复到原来的状态。

                【讨论】:

                • 这将打开一个设置了该环境变量的 bash shell...它不会将其设置在现有容器中。当您退出该外壳时,即使不重新启动容器,您也会丢失它。
                • 来自守护进程的错误响应:没有这样的容器:你的环境键=你的新值
                【解决方案15】:

                使用export VAR=Value

                然后在终端输入printenv 验证设置是否正确。

                【讨论】:

                • 它消失了,因此终端关闭了。
                猜你喜欢
                • 2017-05-11
                • 2020-10-22
                • 1970-01-01
                • 1970-01-01
                • 2019-10-31
                • 2020-01-12
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多