从Docker镜像中删除环境变量

3

我在网上搜索并尝试了显而易见的方法(如下所述)来从Docker镜像中删除环境变量。

1- 我使用以下命令从修改过的Ubuntu镜像创建容器:

docker run -it --name my_container my_image

2- 我检查镜像并使用以下命令查看要删除的两个环境变量:

docker inspect my_container

这将返回:

Original Answer:

...
    "Env": [
        "env_variable_1=abcdef",
        "env_variable_2=ghijkl",
        "env_variable_3=mnopqr",
...

3 - 我进入容器并通过以下方式删除环境变量:

最初的回答:

docker exec -it my_container bash
unset env_variable_1
unset env_variable_2

4- 我检查确保指定的变量已经被删除:

最初的回答

docker inspect my_container

最初的回答

这将产生:

...
    "Env": [
        "env_variable_3=mnopqr",
...

5 - 然后通过以下命令将修改后的容器提交为镜像:

docker commit my_container my_new_image

6 - 并通过以下命令检查已删除的环境变量是否存在:

docker inspect my_new_image

“最初的回答”(Original Answer)

docker run -it --name my_new_container my_new_image
docker inspect my_new_container

这将产生(请鼓掌):

最初的回答:

...
    "Env": [
        "env_variable_1=abcdef",
        "env_variable_2=ghijkl",
        "env_variable_3=mnopqr",
...

AKA已删除的变量在使用docker commit命令时不会从修改后的容器传递到新镜像中。
这里我错过了什么?unset是否真的删除了这些变量?我应该使用另一种方法来删除这些环境变量或使用另一种/修改后的方法将容器提交为镜像吗?
PS:通过env确认变量在容器内存在。然后,使用unset my_variable后,使用相同方法确认它们未激活。
谢谢您的帮助!
4个回答

4
您需要编辑构建原始镜像的Dockerfile。Dockerfile ENV 指令 有几种不同的语法来设置变量,但没有一种可以取消设置变量。docker run -e Docker Compose environment: 设置 也无法做到这一点。这并不是特别常见的用例。
根据您的需求,将变量设置为空值可能已经足够了,尽管从技术上讲这是不同的。
FROM my_image
ENV env_variable_1=""
RUN test -z "$env_variable_1" && echo variable 1 is empty
RUN echo variable 1 is ${env_variable_1:-empty}
RUN echo variable 1 is ${env_variable_1-unset}
# on first build will print out "empty", "empty", and nothing

大锤的作用是使用入口脚本取消变量。脚本应该如下所示:
#!/bin/sh
unset env_variable_1 env_variable_2
exec "$@"

它将与类似以下的 Dockerfile 配对:

FROM my_image
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["same", "as", "before"]
docker inspect 仍会显示变量已设置(因为它在容器元数据中),但像 ps e 这样显示容器进程实际环境的命令将显示其未设置。
通常情况下应始终使用 docker build 系统创建镜像,而不要使用 docker commit。 (“修改的 Ubuntu 镜像”实际上并不是一个可重现的调试或寻求帮助的方案,也不适用于在六个月后出现关键安全补丁时进行重建)。docker inspect 并非本质上有害,但其提供了大量无用信息;我很少需要使用它。

2
也许你可以尝试这种方法,就像在这个回答中提到的那样: "最初的回答"。
docker exec -it -e env_variable_1 my_container bash

最初的回答:然后像往常一样提交容器。翻译后的内容:

然后按照平常的步骤提交容器。


注意:在不指定值的情况下使用 -e 变量名可能会起作用,但前提是该变量不存在于您运行 docker 命令的主机环境中。文档说明它旨在通过一个变量传递:“如果操作符命名了一个环境变量而没有指定值,则该命名变量的当前值会传播到容器的环境中”。 - PolyTekPatrick
对我来说,这种方法没有起作用。该方法创建了一个没有设置变量的bash会话。然而,当我稍后连接到容器时没有使用-e参数,变量仍然存在。 - mherzog

1
我个人想要删除所有的环境变量,以获得一个全新的镜像,但又不希望丢失镜像内部的内容。
问题是,当我重新使用这个镜像并重置这些环境变量为新值时,它们没有改变,旧值仍然存在。
我的解决方案是使用docker export重新初始化镜像,然后再使用docker import导出 首先,启动一个包含该镜像的容器,然后将容器导出为一个tarball文件。
docker export container_name > my_image.tar

导入 将tarball导入到新的镜像中
docker import my_image.tar my_image_tag:latest

这样做将重置图像,意味着只有容器的内容会保留下来。 所有层、环境变量、入口点和命令数据都将消失。

0
我编写了一个Shell脚本("proxy-capsule.sh"),我在我的Dockerfile中使用。这个脚本为当前的bash会话设置HTTP代理,并在之后执行实际的命令。
#!/bin/bash
set -eo pipefail

export HTTP_PROXY="$1"
export HTTPS_PROXY="$1"
export NO_PROXY="$2"

export http_proxy="$1"
export https_proxy="$1"
export no_proxy="$2"

shift 2 # discard the first and second script argument

exec "$@" # use the remaining arguments to execute the actual command in the current environment

...然后在Dockerfile中...
FROM postgres:14.6-alpine3.17

ARG HTTP_PROXY
ARG NO_PROXY

# Create app directory and upload proxy-capsule.sh script
RUN mkdir /app
COPY proxy-capsule.sh /app/proxy-capsule.sh

# Update package manager
RUN /app/proxy-capsule.sh $HTTP_PROXY $NO_PROXY apk update

这样,http代理仅针对单个bash会话设置,您无需在入口脚本的启动时将其删除。在我看来,这是更准确的解决方案,因为它会产生一个更干净的Docker镜像。如果容器运行环境需要http代理,则可以使用docker run命令的-e参数指定环境变量。
缺点是,您必须在Dockerfile中的所有命令前加上RUN /app/proxy-capsule.sh $HTTP_PROXY $NO_PROXY,这需要访问互联网。

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