1. 概述

本文将展示如何在Docker中更新PATH变量。首先,我们将全局更新它。然后,我们将限制更改仅应用于一组指令。

2. 全局更新PATH变量

ENV语句可以用来更新PATH变量。让我们编写一个Dockerfile示例来展示这种行为:

FROM ubuntu:latest
RUN echo $PATH
ENV PATH="$PATH:/etc/profile"
RUN echo $PATH

第一行表示我们使用最新的Ubuntu镜像。我们还在ENV指令之前和之后记录了PATH变量的值。

现在让我们构建我们的镜像:

$ docker build -t baeldungimage .
#4 [1/3] FROM docker.io/library/ubuntu:latest
#5 [2/3] RUN echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#5 0.683 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#6 [3/3] RUN echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/profile
#6 0.893 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/profile

如预期的那样,/etc/profile被添加到了PATH中。

3. 只为一组指令更新PATH

我们将使用RUN指令运行一个sh脚本来PATH添加内容。然后,我们将在同一个RUN语句中添加另一个指令。这将在同一个RUN命令内的后续指令中使用更新后的PATH值。我们还将记录全局PATH变量,以确认它未改变。

以下是我们的新Dockerfile:

FROM ubuntu:latest
RUN echo $PATH
RUN export PATH="$PATH:/etc/profile"; echo $PATH
RUN echo $PATH

我们现在可以构建镜像:

$ docker build -t baeldungimage . 
#7 [1/4] FROM docker.io/library/ubuntu:latest
#4 [2/4] RUN echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#4 0.477 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#5 [3/4] RUN export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/profile"; echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#5 0.660 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/profile
#6 [4/4] RUN echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#6 0.661 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

日志证实,在导出PATH变量后,其值被同一RUN命令内后续指令所使用。然而,全局变量并未改变。

4. 在shell会话中更新PATH

接下来,我们将看到如何仅在shell会话中更新PATH。首先,我们将修改.bashrc文件,使其在每个shell会话开始时更新PATH。然后,我们将启动一个shell会话以检查此行为。

4.1. 编辑.bashrc文件

我们将编辑.bashrc文件,在每个shell会话开始时导出新的PATH。为此,我们将运行一个快速脚本向原始文件追加导出,以确保这一更改不会影响全局PATH变量。

以下是新的Dockerfile:

FROM ubuntu:latest
RUN echo $PATH
RUN echo "export PATH=$PATH:/etc/profile" >> ~/.bashrc
RUN cat ~/.bashrc
RUN echo $PATH

另外,请注意我们使用了[cat](/linux/files-cat-more-less#cat)命令查看文件。

现在让我们构建镜像:

$ docker build -t baeldungimage . 
#4 [1/5] FROM docker.io/library/ubuntu:latest
#5 [2/5] RUN echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#5 0.447 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#6 [3/5] RUN echo "export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/profile" >> ~/.bashrc
#7 [4/5] RUN cat ~/.bashrc
#7 0.956 # ~/.bashrc: executed by bash(1) for non-login shells.
#7 0.956 # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
#7 0.956 # for examples
#7 0.956
#7 0.956 # If not running interactively, don't do anything
#7 0.956 [ -z "$PS1" ] && return
[... .bashrc full content]
#7 0.956 export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/profile
#7 DONE 1.0s
#8 [5/5] RUN echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#8 0.867 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

如您所见,全局PATH没有改变。但是,确实已将导出行添加到文件末尾。因此,每当加载.bashrc时,它都会为运行的shell更新PATH变量。

4.2. 运行容器的交互模式

现在,让我们关注我们之前看到的.bashrc文件输出的前几行。这些行来自原始文件。它明确地说明了“如果不在交互模式下运行,则不做任何操作”。

理解这一点很重要:当我们构建Dockerfile时,RUN命令是非交互式的。因此,我们无法仅源代码.bashrc文件并在构建期间运行脚本来检查路径是否已更新。

相反,我们可以运行容器的交互模式,并打开一个shell会话:

$ docker run -it --name interactiveimage baeldungimage
root@18781222594f:/# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/profile

一旦进入shell会话,我们就打印了PATH。我们可以看到/etc/profile被添加,确认.bashrc文件已被考虑。

5. 结论

在这篇教程中,我们看到了如何在Docker中更新PATH变量。最初,我们全局更新了变量,但我们也学习了如何通过更严格的限制来更新它。

正如往常一样,代码可以在GitHub上找到https://github.com/Baeldung/ops-tutorials/tree/main/docker-modules/docker-images