每个Dockerfile RUN调用中的源 [英] source in every Dockerfile RUN call

查看:81
本文介绍了每个Dockerfile RUN调用中的源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Dockerfile, where I am finding myself constantly needing to call 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 调用中对此进行初始化?

Is there a method to have this initialised in every RUN call in a Dockerfile?

尝试添加到〜/.bash_profile 和Docker的 ENV 命令没有任何运气.

Have tried adding to ~/.bash_profile and Docker's ENV command with no luck.

推荐答案

TL; DR:通过将 .sh 脚本复制到/etc/profile.d/并使用 SHELL Dockerfile命令调整默认shell.

TL;DR: what you want is feasible by copying your .sh script in /etc/profile.d/ and using the SHELL Dockerfile command to tweak the default shell.

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

To start with, consider the following sample script setup.sh:

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

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

Then, it can be noted that bash provides the --login CLI option:

当Bash作为交互式登录Shell或使用-login 选项作为非交互式Shell调用时,它首先从文件/etc/profile中读取并执行命令(如果该文件存在).读取该文件后,它将依次搜索〜/.bash_profile 〜/.bash_login 〜/.profile ,并从存在且可读的第一个命令中读取并执行命令.启动外壳程序以禁止此行为时,可以使用-noprofile 选项.

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.

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

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 中附加 setup.sh 代码之外,您还可以利用/etc/profile.d 多数发行版都通过以下方式读取的文件夹:

Furthermore, instead of appending the setup.sh code in /etc/profile, you can take advantage of the /etc/profile.d folder that is read in the following way by most distributions:

$ 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 ).

Note in particular that the .sh extension is mandatory, hence the naming of the minimal-working-example above: setup.sh (not setup.bash).

最后,可以依赖 SHELL 命令替换 RUN (代替 ["/bin/sh","-c"] )所使用的默认外壳) bash -login 选项.

Finally, it is possible to rely on the SHELL command to replace the default shell used by RUN (in place of ["/bin/sh", "-c"]) to incorporate the --login option of bash.

具体来说,您可以像这样对 Dockerfile 进行措辞:

Concretely, you could phrase your Dockerfile like this:

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

这篇关于每个Dockerfile RUN调用中的源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆