每个 Dockerfile RUN 调用中的源



我有一个Dockerfile,我发现自己经常需要调用source /opt/ros/noetic/setup.bash

例如:

RUN source /opt/ros/noetic/setup.bash 
&& SOME_COMMAND
RUN source /opt/ros/noetic/setup.bash 
&& SOME_OTHER_COMMAND

有没有一种方法可以在 Dockerfile 中的每个RUN调用中初始化它?

尝试添加到~/.bash_profile和 Docker 的ENV命令,但没有运气。

TL;DR:你想要的方法是在/etc/profile.d/中复制你的.sh脚本,并使用SHELLDockerfile命令来调整默认的shell。

详:

首先,请考虑以下示例脚本setup.sh

#!/bin/sh
echo "# setup.sh"
ENV_VAR="some value"
some_fun() {
echo "## some_fun"
}

然后,可以注意到 bash 提供了--loginCLI 选项:

当 Bash 作为交互式登录 shell 调用或使用--login选项作为非交互式 shell 调用时,它首先从文件/etc/profile读取并执行命令,如果该文件存在。读取该文件后,它会按该顺序查找~/.bash_profile~/.bash_login~/.profile,并从存在且可读的第一个命令中读取和执行命令。启动 shell 时,可以使用--noprofile选项来禁止此行为。

当交互式登录 shell 退出,或者非交互式登录 shell 执行 exit 内置命令时,Bash 会从文件~/.bash_logout读取并执行命令(如果存在)。

− https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Bash-Startup-Files

此外,您可以利用大多数发行版以以下方式读取的/etc/profile.d文件夹,而不是在/etc/profile中附加setup.sh代码:

$ docker run --rm -i debian:10 cat /etc/profile | tail -n 9
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi

特别要注意的是,.sh扩展是强制性的,因此上面最小工作示例的命名:setup.sh(不是setup.bash)。

最后,可以依靠SHELL命令来替换RUN使用的默认 shell(代替["/bin/sh", "-c"])以合并bash--login选项。

具体来说,你可以这样表达你的Dockerfile

FROM debian:10
# WORKDIR /opt/ros/noetic
# COPY setup.sh .
# RUN . /opt/ros/noetic/setup.sh && echo "ENV_VAR=$ENV_VAR"
# empty var here
RUN echo "ENV_VAR=$ENV_VAR"
# enable the extra shell init code
COPY setup.sh /etc/profile.d/
SHELL ["/bin/bash", "--login", "-c"]
# nonempty var and function
RUN echo "ENV_VAR=$ENV_VAR" && some_fun
# DISABLE the extra shell init code!
RUN rm /etc/profile.d/setup.sh
# empty var here
RUN echo "ENV_VAR=$ENV_VAR"

结果:

$ docker build -t test .
Sending build context to Docker daemon  6.144kB
Step 1/7 : FROM debian:10
---> ef05c61d5112
Step 2/7 : RUN echo "ENV_VAR=$ENV_VAR"
---> Running in 87b5c589ec60
ENV_VAR=
Removing intermediate container 87b5c589ec60
---> 6fdb70be76f9
Step 3/7 : COPY setup.sh /etc/profile.d/
---> e6aab4ebf9ef
Step 4/7 : SHELL ["/bin/bash", "--login", "-c"]
---> Running in d73b0d13df23
Removing intermediate container d73b0d13df23
---> ccbe789dc36d
Step 5/7 : RUN echo "ENV_VAR=$ENV_VAR" && some_fun
---> Running in 42fd1ae14c17
# setup.sh
ENV_VAR=some value
## some_fun
Removing intermediate container 42fd1ae14c17
---> de74831896a4
Step 6/7 : RUN rm /etc/profile.d/setup.sh
---> Running in bdd969a63def
# setup.sh
Removing intermediate container bdd969a63def
---> 5453be3271e5
Step 7/7 : RUN echo "ENV_VAR=$ENV_VAR"
---> Running in 0712cea427f1
ENV_VAR=
Removing intermediate container 0712cea427f1
---> 216a421f5659
Successfully built 216a421f5659
Successfully tagged test:latest

相关内容

  • 没有找到相关文章