在Docker容器中永久更新PATH环境变量

124

我尝试按照以下方法在文件~/.profile/etc/profile中添加到PATH

PATH = $PATH:/required/path

然而,它并没有起作用。然后我尝试添加显示(show)行,但也没有起作用。

export PATH

即使重新启动容器和主机,它仍然无法正常工作。


问题是在创建容器并进行一些修改之后,而不是在使用Docker配置文件创建容器时。 - user859375
6个回答

200
如果您想在Dockerfile中包含一个/new/path,则添加以下行:ENV PATH "$PATH:/new/path"Dockerfile中即可生效。

11
请注意,引号很重要。 - orodbhen
1
这个可以工作,但并不适用于所有用户。有什么办法可以让它对每个人都可用? - MrUpsidown
1
无法使用ENV实现,您需要使用类似于/etc/environment的东西:https://github.com/moby/moby/issues/15383 - kossmoboleat
1
这对我来说很有效。我需要将JDK添加到一个镜像中(我不能只使用apt install,必须单独下载和提取),所以我添加了ENV JAVA_HOME "/path/to/jdk"和ENV PATH "${JAVA_HOME}/bin:${PATH}"。一旦我重建了镜像,JDK就可以供构建用户使用了。 - Spanky Quigman
在IBM的LSF中,有没有特殊的方法来做这件事? - Brian Wiley
如果指定了USER,则此方法无效。echo $PATH显示正确的路径,但shell不会遵守路径更改。 - RMorrisey

39

1. 正确的回答

最佳投票答案建议在Dockerfile中添加ENV PATH "$PATH:/new/path",这应该有效。

2. 为什么我不能用呢?

正如某些评论/答案所指出的那样,解决方案1对一些人不起作用。

原因是当运行docker容器时,PATH可能被一些脚本(如.bashrc)覆盖,从而给人留下了ENV PATH...没有工作的印象,但理论上它确实工作了。

要解决此问题,您需要通过将以下命令添加到Dockerfile来附加正确的PATH.bashrc

RUN echo "export PATH=/new/path:${PATH}" >> /root/.bashrc


1
好的,但是如何重新加载环境,以便bash看到更改? - Alexander
1
@Alexander 你可以使用. /root/.bashrc命令在现有的bash会话中引用更新后的文件。否则,当打开一个新的会话时,默认情况下应该会捕获到这个更改。 - erran

13

12

我在IRC聊天中获得了这个问题的答案,并将其提供给可能遇到此问题的任何人。很多人都给出了错误的答案,比如要更新~/.profile文件,但那并不起作用。所以请使用以下答案。

对于用户,请更新文件~/.bashrc,对于全局更改,请更新/etc/environment文件。这将应用于所有用户。

.bashrc文件中,导出路径:export PATH=$PATH:/new/path/bin

在环境变量文件中:PATH=$PATH:/new/path/bin


我认为考虑到问题涉及Docker,Jason Gao的回答应该被接受。在标准的非容器化环境中更新bash配置文件是存储变量的好方法,但如果您正在容器中部署,则最好在Dockerfile中包含ENV步骤,这样更加清晰。 - NiallJG
2
根据这份Ubuntu文档,'in environment'方法不正确(注意:变量扩展在/etc/environment中无效)。https://help.ubuntu.com/community/EnvironmentVariables#A.2Fetc.2Fenvironment - dangeroushobo
所以设置 .bashrc 文件似乎只有在作为交互式终端运行时才有效,这很合理,因为它将运行用户默认的 shell。除非通过 bash 发送命令,否则使用该文件无法在容器内部运行命令。 - Alex Barker
1
有人能修改一下吗?我刚刚浪费了一个小时,一直在想为什么它不会扩展。谢谢 @dangeroushobo - MrR

7
交互式和非交互式 shell 的区别并未被注意到。因此,这就是为什么上面的解决方案有时似乎有效,有时却不起作用。
非交互式 shell 通常会跳过 bashrc 文件。例如在 Debian 中,/etc/bash.bashrc 文件非常清楚地说明:
# System-wide .bashrc file for interactive bash(1) shells.

# To enable the settings / commands in this file for login shells as well,
# this file has to be sourced in /etc/profile.

# If not running interactively, don't do anything
[ -z "$PS1" ] && return
  • Dockerfile中的RUN命令调用了一个非交互式shell,并且所设置的ENV路径以及bashrc脚本将不会被运行。
  • docker run -it <image> /bin/bash 调用了一个交互式shell。 bashrc 将被运行,如果在任何一个bashrc脚本中没有按照通常的 PATH=$PATH:/... 语法来定义PATH,那么它可以覆盖任何由ENV设置的内容。

为了在这两种模式之间保持安全和一致,可以在Dockerfile中进行如下设置:

ENV PATH /master/go/bin:${PATH}
RUN echo "${PATH}" >> /etc/bash.bashrc

请注意,/etc/bash.bashrc 是Debian的位置,在其他发行镜像上可能不同。

2
这是我的Docker文件,在CentOS上我已经提取并设置了Java的主目录路径,并且它对我起作用了。
Docker文件:
FROM  centos:7
RUN yum update -y yum install -y tar
COPY jdk-7u80-linux-x64.tar.gz /opt/
WORKDIR /opt
RUN tar -xvf jdk-7u80-linux-x64.tar.gz
RUN chmod -R 755 jdk1.7.0_80
RUN echo export JAVA_HOME=/opt/jdk1.7.0_80 >> /etc/profile
RUN echo export PATH='$PATH:$JAVA_HOME/bin' >> /etc/profile
ENV JAVA_HOME "/opt/jdk1.7.0_80"
ENV PATH "${JAVA_HOME}/bin:${PATH}"

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