在 Dockerfile 中,如何更新 PATH 环境变量?

Posted

技术标签:

【中文标题】在 Dockerfile 中,如何更新 PATH 环境变量?【英文标题】:In a Dockerfile, How to update PATH environment variable? 【发布时间】:2015-01-21 12:03:49 【问题描述】:

我有一个 dockerfile 可以从源代码下载和构建 GTK,但以下行没有更新我的图像的环境变量:

RUN PATH="/opt/gtk/bin:$PATH"
RUN export PATH

我读到我应该使用 ENV 来设置环境值,但以下指令似乎也不起作用:

ENV PATH /opt/gtk/bin:$PATH

这是我的整个 Dockerfile:

FROM ubuntu
RUN apt-get update
RUN apt-get install -y golang gcc make wget git libxml2-utils libwebkit2gtk-3.0-dev libcairo2 libcairo2-dev libcairo-gobject2 shared-mime-info libgdk-pixbuf2.0-* libglib2-* libatk1.0-* libpango1.0-* xserver-xorg xvfb

# Downloading GTKcd
RUN wget http://ftp.gnome.org/pub/gnome/sources/gtk+/3.12/gtk+-3.12.2.tar.xz
RUN tar xf gtk+-3.12.2.tar.xz
RUN cd gtk+-3.12.2

# Setting environment variables before running configure
RUN CPPFLAGS="-I/opt/gtk/include"
RUN LDFLAGS="-L/opt/gtk/lib"
RUN PKG_CONFIG_PATH="/opt/gtk/lib/pkgconfig"
RUN export CPPFLAGS LDFLAGS PKG_CONFIG_PATH
RUN ./configure --prefix=/opt/gtk
RUN make
RUN make install

# running ldconfig after make install so that the newly installed libraries are found.
RUN ldconfig

# Setting the LD_LIBRARY_PATH environment variable so the systems dynamic linker can find the newly installed libraries.
RUN LD_LIBRARY_PATH="/opt/gtk/lib"

# Updating PATH environment program so that utility binaries installed by the various libraries will be found.
RUN PATH="/opt/gtk/bin:$PATH"
RUN export LD_LIBRARY_PATH PATH

# Collecting garbage
RUN rm -rf gtk+-3.12.2.tar.xz

# creating go code root
RUN mkdir gocode
RUN mkdir gocode/src
RUN mkdir gocode/bin
RUN mkdir gocode/pkg

# Setting the GOROOT and GOPATH enviornment variables, any commands created are automatically added to PATH
RUN GOROOT=/usr/lib/go
RUN GOPATH=/root/gocode
RUN PATH=$GOPATH/bin:$PATH
RUN export GOROOT GOPATH PATH

【问题讨论】:

LD_LIBRARY_PATH 和 PATH 应该使用 ENV 设置而不是导出。您也 LD_LIBRARY_PATH 不应该指向 PATH!。删除 Dockerfile 中的文件不会让你的镜像变小,请查看centurylinklabs.com/optimizing-docker-images/?hvid=4wO7Yt。 当前的 dockerfile 是否有效? @HuiWang 可能不会。它是 1.5 年前写的,从那以后发生了很多变化。只需确保合并所选答案中描述的更改即可。 【参考方案1】:

您可以在Dockerfile 中使用Environment Replacement,如下所示:

ENV PATH="/opt/gtk/bin:$PATH"

【讨论】:

= 是否需要等号? @IgorGanapolsky 不在此实例中,因为它指定了单个变量。但是,在指定多个变量时,它不会受到伤害并且是强制性的。有关详细信息,请参阅ENV documentation。 行得通!请注意= 它必须没有空格。如果你在 = 旁边添加空格,像这样 ENV PATH = "/opt/gtk/bin:$PATH" 会破坏你的 $PATH 这不会更新带有主机$PATH 附加的图像吗? ENV PATH="/opt/gtk/bin:$PATH" 可能与ENV PATH="/opt/gtk/bin:$PATH" 不同,前者带有大括号,可能会为您提供主机的 PATH。文档并未暗示会出现这种情况,但我观察到确实如此。这很容易检查只需执行 RUN echo $PATH 并将其与 RUN echo $PATH 进行比较【参考方案2】:

虽然 Gunter 发布的答案是正确的,但它与我已经发布的并没有什么不同。问题不是ENV指令,而是后续指令RUN export $PATH

一旦您在 Dockerfile 中通过ENV 声明了环境变量,就无需导出环境变量。

RUN export ... 行一删除,我的镜像就构建成功了

【讨论】:

RUN A=BRUN export ARUN export A=B 是有效的 shell 命令,但影响在同一 RUN 指令中的命令的环境 (但没有给出)。同样,如果您有RUN export PATH=/foo; prog1; prog2;(在同一个RUN 中),PATH 修改将影响prog1prog2。因此,RUN export $PATH 是一个 noop(因为没有程序使用该修改后的环境),并且该指令是否存在应该没有区别。 “Gunter”是指this answer? 修复实际上是使用 ENV 指令更改 PATH 值,而不是 RUN。然后,当 docker builder 调用以下 RUN 时,这些更改将继续存在。【参考方案3】:

[我在回应所选答案时提到了这一点,但建议将其作为自己的答案更加突出]

需要注意的是

ENV PATH="/opt/gtk/bin:$PATH" 

可能不一样

ENV PATH="/opt/gtk/bin:$PATH" 

带有大括号的前者可能会为您提供主机的路径。文档并未暗示会出现这种情况,但我观察到确实如此。这很容易检查,只需执行 RUN echo $PATH 并将其与 RUN echo $PATH 进行比较

【讨论】:

刚刚尝试验证这个断言,两个命令给出了相同的输出。使用 docker 20.10.2. 我刚在 Mac 上用 20.10.2 试了一下,两者不一样。 $PATH 包含我笔记本电脑上的路径(例如 /Library/... 和 /Users/...),而 $PATH 仅反映容器上下文中的路径。 最新的 docs.docker.com/engine/reference/builder/… 说“环境变量在 Dockerfile 中用 $variable_name 或 $variable_name 表示。它们被同等对待” 嗯...“等价”并不一定意味着“完全相同”。我建议任何有兴趣的人检查一下这是否适用于 $PATH 和 $PATH。 20.10.6 仍然有不同的行为。 这太疯狂了。我也看到了不同的输出。【参考方案4】:

不鼓励这样做(如果您想创建/分发干净的 Docker 映像),因为 PATH 变量是由 /etc/profile 脚本设置的,所以可以覆盖该值。

head /etc/profile:

if [ "`id -u`" -eq 0 ]; then
  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
  PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
fi
export PATH

在 Dockerfile 的末尾,您可以添加:

RUN echo "export PATH=$PATH" > /etc/environment

因此为所有用户设置了 PATH。

【讨论】:

根据this Ubuntu documentation,/etc/environment 是赋值表达式的列表,而不是脚本,并且不支持变量扩展,因此RUN 语法不太可能起作用。跨度> 是的,它将被扩展并且export PATH=<some path> 将被写入/etc/environment,这仍然不正确,因为该文件不是脚本而是<var name>=<value> 的列表。 export 可能会失败,除非您的系统支持超出规范的一些黑魔法。

以上是关于在 Dockerfile 中,如何更新 PATH 环境变量?的主要内容,如果未能解决你的问题,请参考以下文章

dockerfile详解

docker中的dockerfile

dockerfile学习与详解

Dockerfile简单使用入门

Dockerfile 之 WORKDIR

Dockerfile参考