每个 Dockerfile 运行 调用中的源代码
source in every Dockerfile RUN call
我有一个 Docker 文件,我发现自己经常需要调用 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
是否有一种方法可以在 Docker 文件中的每个 RUN
调用中进行初始化?
已尝试添加到 ~/.bash_profile
和 Docker 的 ENV
命令,但没有成功。
TL;DR: 通过将 .sh
脚本复制到 /etc/profile.d/
并使用 SHELL
Dockerfile 命令来实现您想要的是可行的调整默认 shell.
详情:
首先,考虑以下示例脚本 setup.sh
:
#!/bin/sh
echo "# setup.sh"
ENV_VAR="some value"
some_fun() {
echo "## some_fun"
}
然后,可以注意到 bash 提供了 --login
CLI 选项:
When Bash is invoked as an interactive login shell, or as a non-interactive shell with the --login
option, it first reads and executes commands from the file /etc/profile
, if that file exists. After reading that file, it looks for ~/.bash_profile
, ~/.bash_login
, and ~/.profile
, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile
option may be used when the shell is started to inhibit this behavior.
When an interactive login shell exits, or a non-interactive login shell executes the exit builtin command, Bash reads and executes commands from the file ~/.bash_logout
, if it exists.
− 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
command 替换 RUN
使用的默认 shell(代替 ["/bin/sh", "-c"]
)来合并 [= bash
.
的 18=] 选项
具体来说,您可以这样表达您的 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
我有一个 Docker 文件,我发现自己经常需要调用 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
是否有一种方法可以在 Docker 文件中的每个 RUN
调用中进行初始化?
已尝试添加到 ~/.bash_profile
和 Docker 的 ENV
命令,但没有成功。
TL;DR: 通过将 .sh
脚本复制到 /etc/profile.d/
并使用 SHELL
Dockerfile 命令来实现您想要的是可行的调整默认 shell.
详情:
首先,考虑以下示例脚本 setup.sh
:
#!/bin/sh
echo "# setup.sh"
ENV_VAR="some value"
some_fun() {
echo "## some_fun"
}
然后,可以注意到 bash 提供了 --login
CLI 选项:
When Bash is invoked as an interactive login shell, or as a non-interactive shell with the
--login
option, it first reads and executes commands from the file/etc/profile
, if that file exists. After reading that file, it looks for~/.bash_profile
,~/.bash_login
, and~/.profile
, in that order, and reads and executes commands from the first one that exists and is readable. The--noprofile
option may be used when the shell is started to inhibit this behavior.When an interactive login shell exits, or a non-interactive login shell executes the exit builtin command, Bash reads and executes commands from the file
~/.bash_logout
, if it exists.− 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
command 替换 RUN
使用的默认 shell(代替 ["/bin/sh", "-c"]
)来合并 [= bash
.
具体来说,您可以这样表达您的 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