【问题标题】:`bash: webots: command not found` in my docker container because of multiple FROMs`bash: webots: command not found` 在我的 docker 容器中,因为有多个 FROM
【发布时间】:2021-06-17 23:09:54
【问题描述】:

我有一个安装了 Webots 和 ROS2 的 docker 容器。但是,在容器内运行webots 会返回bash: webots: command not found。为什么?

运行 webots(但没有 ROS2)的容器

这是一个从Webots installation instructions 运行的容器,确实 成功运行了webots(但缺少我需要的 ROS2):

$ xhost +local:root > /dev/null 2>&1 #so webots won't say unable to load Qt platform plugin "xcb"
$ docker run -it -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw cyberbotics/webots:R2021a-ubuntu20.04

不运行的容器webots

这是我的 docker 容器,它没有成功运行webots,而是显示bash: webots: command not found。但是,它确实成功运行webots_ros2 demos(我认为问题与我如何从两个容器继承有关,因为如果我交换我的两个ARGFROM 语句的顺序,则找到webotsros2 不是。虽然我不确定解决方案):

Dockerfile

# inherit both the ROS2 and Webots containers
ARG BASE_IMAGE_WEBOTS=cyberbotics/webots:R2021a-ubuntu20.04
ARG IMAGE_ROS2=niurover/ros2_foxy:latest

FROM $BASE_IMAGE_WEBOTS AS base
FROM $IMAGE_ROS2 AS image_ros2

# resolve a missing dependency for webots demo
RUN apt-get update && apt-get install -y \
        libxtst6 \
        && apt-get clean \
        && rm -rf /var/lib/apt/lists/*

# Finally open a bash command to let the user interact
CMD ["/bin/bash"]

launch.sh(用于启动 docker 容器)

#! /bin/bash
 
CONTAINER_USER=$USER
CONTAINER_NAME=webots_ros2_foxy
USER_ID=$UID
IMAGE=niurover/webots_ros2_foxy:latest
if [ $(uname -r | sed -n 's/.*\( *Microsoft *\).*/\1/ip') ];
then
    xhost +local:$CONTAINER_USER
    xhost +local:root
fi

sudo docker run -it --rm \
    --name $CONTAINER_NAME \
    --user=$USER_ID\
    --env="DISPLAY" \
    --env="CONTAINER_NAME=$CONTAINER_NAME" \
    --workdir="/home/$CONTAINER_USER" \
    --volume="/home/$CONTAINER_USER:/home/$CONTAINER_USER" \
    --volume="/etc/group:/etc/group:ro" \
    --volume="/etc/passwd:/etc/passwd:ro" \
    --volume="/etc/shadow:/etc/shadow:ro" \
    --volume="/etc/sudoers.d:/etc/sudoers.d:ro" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    $IMAGE bash\

if [ $(uname -r | sed -n 's/.*\( *Microsoft *\).*/\1/ip') ];
then
    xhost -local:$CONTAINER_USER
    xhost -local:root
fi

总结

如您所见,两个容器都使用cyberbotics/webots:R2021a-ubuntu20.04,第二个容器使用第一个容器的所有选项,但有一些额外的选项。为什么第一个容器运行webots成功,而第二个容器找不到命令?

【问题讨论】:

  • 您是否设置了WEBOTS_HOME 环境变量?您是否尝试使用 /usr/local/webots/webots 启动 webbot?
  • @OlivierMichel /usr/local/webots/ 没有这样的文件或目录,因此export WEBOTS_HOME=/usr/local/webots 没有多大帮助
  • 我认为这个问题与我如何从两个容器继承有关。如果我交换我的两个ARGFROM 语句的顺序,则找到webots,但找不到ros2。我会将此信息添加到帖子中。

标签: docker dockerfile webots


【解决方案1】:

我最终采用了 Leonardo Dagnino 的建议,并且奏效了。我不得不复制几个连续的 ROS2 容器的内容,以使树层次结构脱离 webbots 基础映像,但它让我得到了我要去的地方。为了繁荣,这里是完整的新 Dockerfile:

# Use Webots docker container as base
ARG BASE_IMAGE_WEBOTS=cyberbotics/webots:R2021a-ubuntu20.04
FROM $BASE_IMAGE_WEBOTS AS base

# ==================================================================================
# niurover/ros2_foxy uses osrf/ros:foxy-desktop as its base, so I need to add code from
# container heirarchy all the way back to where it can stem off of `base` from above
# ==================================================================================

# ----------------------------------------------------------------------------------
# taken from Dockerfile for ros:foxy-ros-core-focal found at:
# https://github.com/osrf/docker_images/blob/master/ros/foxy/ubuntu/focal/ros-core/Dockerfile
# ----------------------------------------------------------------------------------

## setup timezone   # NOTE commented out since timezone should already be set up
#RUN echo 'Etc/UTC' > /etc/timezone && \
#    ln -s /usr/share/zoneinfo/Etc/UTC /etc/localtime && \
#    apt-get update && \
#    apt-get install -q -y --no-install-recommends tzdata && \
#    rm -rf /var/lib/apt/lists/*

# install packages
RUN apt-get update && apt-get install -q -y --no-install-recommends \
    dirmngr \
    gnupg2 \
    && rm -rf /var/lib/apt/lists/*

# setup keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

# setup sources.list
RUN echo "deb http://packages.ros.org/ros2/ubuntu focal main" > /etc/apt/sources.list.d/ros2-latest.list

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

ENV ROS_DISTRO foxy

# install ros2 packages
RUN apt-get update && apt-get install -y --no-install-recommends \
    ros-foxy-ros-core=0.9.2-1* \
    && rm -rf /var/lib/apt/lists/*

## setup entrypoint # NOTE ignore this part of their Dockerfile
#COPY ./ros_entrypoint.sh /
#
#ENTRYPOINT ["/ros_entrypoint.sh"]
#CMD ["bash"]

# ----------------------------------------------------------------------------------
# taken from Dockerfile for ros:foxy-ros-base-focal found at:
# https://github.com/osrf/docker_images/blob/master/ros/foxy/ubuntu/focal/ros-base/Dockerfile
# ----------------------------------------------------------------------------------

# install bootstrap tools
RUN apt-get update && apt-get install --no-install-recommends -y \
    build-essential \
    git \
    python3-colcon-common-extensions \
    python3-colcon-mixin \
    python3-rosdep \
    python3-vcstool \
    && rm -rf /var/lib/apt/lists/*

# bootstrap rosdep
RUN rosdep init && \
  rosdep update --rosdistro $ROS_DISTRO

# setup colcon mixin and metadata
RUN colcon mixin add default \
      https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml && \
    colcon mixin update && \
    colcon metadata add default \
      https://raw.githubusercontent.com/colcon/colcon-metadata-repository/master/index.yaml && \
    colcon metadata update

# install ros2 packages
RUN apt-get update && apt-get install -y --no-install-recommends \
    ros-foxy-ros-base=0.9.2-1* \
    && rm -rf /var/lib/apt/lists/*

# ----------------------------------------------------------------------------------
# taken from Dockerfile for osrf/ros:foxy-desktop-focal (or is it osrf/ros:foxy-desktop?) found at:
# https://github.com/osrf/docker_images/blob/master/ros/foxy/ubuntu/focal/desktop/Dockerfile 
# ----------------------------------------------------------------------------------
  
# This is an auto generated Dockerfile for ros:desktop
# generated from docker_images_ros2/create_ros_image.Dockerfile.em
#FROM ros:foxy-ros-base-focal   # NOTE commented out since satisfied by above

# install ros2 packages
RUN apt-get update && apt-get install -y --no-install-recommends \
    ros-foxy-desktop=0.9.2-1* \
    && rm -rf /var/lib/apt/lists/*

# ----------------------------------------------------------------------------------
# taken from Dockerfile for niurover/ros2_foxy found at:
# https://github.com/NIURoverTeam/Dockerfiles/blob/master/ros2_foxy/Dockerfile
# ----------------------------------------------------------------------------------
#ARG BASE_IMAGE=osrf/ros:foxy-desktop   # NOTE commented out since satisfied by above

# Install work packages
#FROM $BASE_IMAGE as base   # NOTE commented out since satisfied by above
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
        tmux \
        curl \
        wget \
        vim \
        sudo \
        unzip \
        python3-pip \
        && apt-get clean \
        && rm -rf /var/lib/apt/lists/*

# Install ROS Packages
RUN apt-get update && apt-get install -y \
        ros-foxy-turtlesim \
        ~nros-foxy-rqt* \
        ros-foxy-teleop-tools \
        ros-foxy-joy-linux \
        && apt-get clean \
        && rm -rf /var/lib/apt/lists/*

RUN pip3 install pyserial

#CMD ["bash"]   # NOTE ignore this part of the Dockerfile

# ----------------------------------------------------------------------------------
# new stuff added on top of niurover/ros2_foxy to assist with Webots + ROS2
# ----------------------------------------------------------------------------------

# resolve a missing dependency for webots demo
RUN apt-get update && apt-get install -y \
        libxtst6 \
        && apt-get clean \
        && rm -rf /var/lib/apt/lists/*

# Finally open a bash command to let the user interact
CMD ["/bin/bash"]

【讨论】:

    【解决方案2】:

    当您有多个 FROM 命令时,您并没有将它们的两个内容“继承”到同一个图像中 - 您正在执行 multi-stage build。这使您可以从指定--from 选项的那个阶段开始COPY。默认情况下,您的 Dockerfile 中的最后一个阶段将是目标(因此,在您的示例中,您实际上只是在使用 ros2 映像。webbots 映像实际上并没有在那里使用。

    你有两个选择:

    1. 使用COPY --from=base从webbots镜像中复制你需要的文件

    这可能会很困难和挑剔。您需要复制所有依赖项;如果它们是通过您的包管理器 (apt-get) 获取的,您将导致 dpkg 的本地数据库不一致。

    1. 复制Dockerfiles 之一并更改其FROM

    只要它们都使用相同的基本分布,这可能会正常工作。您可以进入项目的一个存储库并获取他们的Dockerfile,从另一个映像重建它——只需将cyberbotics/webots:R2021a-ubuntu20.04 的Dockerfile 更改为FROM niurover/ros2_foxy:latest。不过,它可能需要修改那里的其他命令。

    【讨论】:

    • 感谢您的评论。我同意选项 1 似乎很挑剔。至于选项2,有没有办法不重复代码?我确实有 niurover/ros2_foxy 的 Dockerfile,但我不愿意只是复制粘贴内容并为自己制造可维护性问题。有什么办法可以避免这种情况吗?也许是 docker compose 或一些 bash 诡计(修改 ARG)?
    • 老实说,我想不出什么好方法。您可以执行sed s/FROM <original image>/FROM cyberbotics/webots:R2021a-ubuntu20.04/ 之类的操作,但这不包括您可能需要进行的任何其他更改,而不仅仅是更改基本映像。对我来说,仅复制 dockerfile 似乎是最不痛苦的选择。
    • 我最终选择了您的选项 2,并且成功了。我不得不在 ROS2 依赖树上向上走一点,以使基本分布对齐,但它完成了工作。如果您想查看完整的 Dockerfile,我将其放在单独的答案中并接受了您的。感谢您的帮助!
    猜你喜欢
    • 2019-07-07
    • 2017-04-08
    • 2014-07-01
    • 2018-07-18
    • 2010-12-09
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 2019-06-06
    相关资源
    最近更新 更多