bash - 每个 Dockerfile RUN 调用中的源

标签 bash docker ubuntu dockerfile ros

我有一个 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
有没有一种方法可以在每个 RUN 中初始化它?调用 Dockerfile?
已尝试添加到 ~/.bash_profile和 Docker 的 ENV命令没有运气。

最佳答案

TL;DR: 通过复制您的.sh,您想要什么是可行的/etc/profile.d/ 中的脚本并使用 SHELL用于调整默认 shell 的 Dockerfile 命令。
细节:
首先,请考虑以下示例脚本 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


此外,而不是附加 setup.sh代码在 /etc/profile ,您可以利用 /etc/profile.d大多数发行版以下列方式读取的文件夹:
$ 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"] )合并 --login 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

关于bash - 每个 Dockerfile RUN 调用中的源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64907049/

相关文章:

docker - 具有多个后端端口的kubernetes负载均衡器

PHP pcntl模块安装

bash - 在 Azure 管道中,linux 命令在脚本文件末尾被截断

linux - bash 错误 : find: I cannot figure out how to interpret ‘2018-26-01’ as a date or time

bash - 如何在 Bash 中使用正负索引获取子字符串

docker - 如何调试dist/不在Docker Cloud Build上生成?

javascript - MongoDB init-script 未使用 docker-compose 启动

linux - 使用共享库的问题

linux - 统计bash中可执行文件的数量

linux - 当存在多个用户进程时从 processid 获取用户