docker - 如何在 dockerfile 中取消设置“ENV”?
问题描述
由于某些特定原因,我必须ENV
在我的 dockerfile 中设置“http_proxy”和“https_proxy”。我现在想取消设置它们,因为还有一些构建过程无法通过代理完成。
# dockerfile
# ... some process
ENV http_proxy=http://...
ENV https_proxy=http://...
# ... some process that needs the proxy to finish
UNSET ENV http_proxy # how to I unset the proxy ENV here?
UNSET ENV https_proxy
# ... some process that can't use the proxy
解决方案
这取决于您要达到的效果。
请注意,作为语用问题(即开发人员实际说话的方式),“取消设置变量”可能意味着两件事:将其从环境中删除,或将变量设置为空值。从技术上讲,这是两种不同的操作。在实践中,虽然我没有遇到我试图控制的软件区分环境中不存在的变量和环境中存在但设置为空值的变量的情况。我通常可以使用任何一种方法来获得相同的结果。
如果您不关心变量是否在 Docker 生成的层中,但将其保留为非空值会导致后续构建步骤出现问题。
对于这种情况,您可以ENV VAR_NAME=
在 Dockerfile 中要取消设置变量的位置使用。语法说明:Docker 允许两种语法ENV
:这ENV VAR=1
与ENV VAR 1
. 您可以使用空格或等号将变量名称与值分开。当您想通过将变量设置为空值来“取消设置”变量时,您必须使用等号语法,否则在构建时会出现错误。
例如,您可以这样做:
ENV NOT_SENSITIVE some_value
RUN something
ENV NOT_SENSITIVE=
RUN something_else
something
运行时,NOT_SENSITIVE
设置为some_value
。something_else
运行时,NOT_SENSITIVE
设置为空字符串。
重要的是要注意,unset NOT_SENSITIVE
作为 shell 命令执行不会影响除此 shell 中执行的内容之外的任何其他内容。这是一个例子:
ENV NOT_SENSITIVE some_value
RUN unset NOT_SENSITIVE && printenv NOT_SENSITIVE || echo "does not exist"
RUN printenv NOT_SENSITIVE
第一个RUN
将打印does not exist
,因为NOT_SENSITIVE
在printenv
执行时未设置,并且因为未设置printenv
返回导致执行的非零退出代码echo
。第二个RUN
不受unset
第一个影响RUN
。它将打印some_value
到屏幕上。
但是,如果我需要从环境中删除变量,而不仅仅是将其设置为空值怎么办?
在这种情况下,使用ENV VAR_NAME=
将不起作用。我不知道有什么方法可以告诉 Docker “从现在开始,您必须从环境中删除这个变量,而不仅仅是将其设置为空值”。
如果您仍想使用ENV
来设置您的变量,那么您必须在每个RUN
要取消设置变量的地方开始使用unset VAR_NAME
,这将只针对特定的情况取消设置RUN
。
如果要防止变量出现在 Docker 生成的层中。
假设该变量包含一个秘密,并且该层可能落入不应拥有该秘密的人手中。在这种情况下,您不能使用ENV
来设置变量。一个变量集ENV
被烘焙到它所应用的层中,并且不能从这些层中删除。特别是(假设变量名为SENSITIVE
)运行
RUN unset SENSITIVE
不做任何事情来将其从图层中删除。上面的命令仅从启动的 shell 进程中unset
删除。它只影响那个外壳。它不会影响由,或通过在命令行运行提供的任何命令生成的 shell。SENSITIVE
RUN
CMD
ENTRYPOINT
docker run
为了防止层包含秘密,我会使用docker build --secret=
and RUN --mount=type=secret...
。例如,假设我已经将我的秘密存储在一个名为 的文件中sensitive
,我可以有RUN
这样的:
RUN --mount=type=secret,id=sensitive,target=/root/sensitive \
export SENSITIVE=$(cat /root/sensitive) \
&& [[... do stuff that requires SENSITIVE ]] \
请注意,给定的命令RUN
不需要以unset SENSITIVE
. 由于进程及其环境的管理方式,SENSITIVE
在生成的 shell 中进行设置RUN
不会产生超出 shell 本身生成的任何影响。此 shell 中的环境更改不会影响未来的 shell,也不会影响 Docker 烘焙到它创建的层中的内容。
然后构建可以运行:
$ DOCKER_BUILDKIT=1 docker build --secret id=secret,src=path/to/sensitive [...]
该docker build
命令的环境需要DOCKER_BUILDKIT=1
使用 BuildKit,因为这种传递秘密的方法只有在 Docker 使用 BuildKit 构建镜像时才可用。
推荐阅读
- python - 创建从 API .py 到 .exe 的可执行文件,当在控制台中执行 .py 时,会将参数发送给它
- git - 在 GitHub 中意外创建的子模块文件夹
- sql - 从 SQL 中的 3 个字符串创建日期列
- java - JavaFX-11/macOS:DirectoryChooser 崩溃“NSObjectNotAvailableException”
- reactjs - React material-ui Select 组件的标签显示在内容之上
- google-ads-api - google adwords 转换跟踪可以通过后端集成来实现吗?
- vba - 使用 MS Access VBA 从 Outlook 发送电子邮件
- uwp - UWP 从背景开始音频
- ssas - 排除总和度量的最后一个事实行
- google-apps-script - 在允许查看者访问幻灯片演示文稿之前,我可以使用 Slides API 添加“同意条款”对话框吗?