ROS 安装后 Dockerfile 运行 命令停止工作

Dockerfile RUN command stops working after ROS install

我正在按照 dockerfile 中 http://wiki.ros.org/noetic/Installation/Ubuntu 的指示安装 ROS。安装后,您使用 'source /opt/ros/noetic/setup.bash' 设置环境。但是,在我这样做之后,dockerfile 中的每个 运行 命令都停止正常工作。

在下面的 dockerfile 中,第一个 'ls /' 产生了预期的输出,但第二个没有。这不是 'ls' 特有的,这只是问题的演示;我在ROS环境下运行后的每一个命令都没有达到预期的效果。 ROS 环境设置中发生了什么来破坏它,我该如何防止它?设置 ROS 后,我还有很多其他设置需要进行。

FROM ubuntu:20.04

# Dependencies
RUN apt-get update && apt-get install -y lsb-release && apt-get clean all
RUN apt-get install -y gnupg2

# Set timezone so tzdata is not interactive during install
ENV TZ=America/New_York
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# Install ROS, from http://wiki.ros.org/noetic/Installation/Ubuntu
RUN sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
RUN apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 && \
    apt-get update && \
    apt install -qq -y ros-noetic-ros-base

RUN apt-get install -y python3-pip
RUN python3 -m pip install rospkg

RUN echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc

# This DOES produce what you would think
RUN ls /

SHELL ["/bin/bash", "-c", "source ~/.bashrc"]

# This DOES NOT produce what you would think
RUN ls /

Dockerfile SHELL 指令更改了用于解释 RUN 命令的 shell。默认是["/bin/sh", "-c"],所以你得到

# These two commands are identical with the default SHELL
RUN ls /
RUN ["/bin/sh", "-c", "ls /"]

当你写 SHELL 时,你会得到

SHELL ["/bin/bash", "-c", "source ~/.bashrc"]
RUN ls /
# Equivalently:
RUN ["/bin/bash", "-c", "source ~/.bashrc", "ls /"]

然而,sh -c选项读取单个命令字并执行它;任何其他选项都将被忽略(主要是;命令词将它们视为 </code> 位置参数)。</p> <p>大多数在 Docker 中,shell 像 <code>.bashrc 这样的点文件被完全忽略。使用 ENV 指令设置环境变量更好。对于单个主容器进程,您还可以使用入口点包装器脚本来加载变量文件,但这在容器构建期间或 docker exec 调试 shells.[=26] 中不起作用=]

您可以利用 sh -c 的特定语义,并且知道该命令将作为单个附加参数传递,然后说

SHELL ["/bin/bash", "-c", ". ~/.bashrc && "]

instead :

# Tell bash these are "login" shells and _should_ read shell dotfiles
SHELL ["/bin/bash", "--login", "-c"]