diff --git a/docker/dockerfile-suave b/docker/dockerfile-suave index ebadb8a..2d27496 100644 --- a/docker/dockerfile-suave +++ b/docker/dockerfile-suave @@ -1,3 +1,4 @@ +# syntax=docker/dockerfile:1 ARG BASE_IMAGE="ghcr.io/kas-lab/kasm-jammy:latest" FROM $BASE_IMAGE @@ -23,7 +24,7 @@ RUN apt update && apt install -y \ libglx-mesa0 \ bash-completion \ python3-pip \ - && rm -rf /var/lib/apt/list/ + && rm -rf /var/lib/apt/lists/* # Set the locale RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ @@ -75,22 +76,30 @@ WORKDIR $HOME # Git commit SHAs — passed in by build_docker_images.sh from docker/versions.env ARG ARDUSUB_COMMIT=571e8c7bd3793fce1bc5184a2f6586feb8a616e5 ARG ARDUPILOT_GAZEBO_COMMIT=082a0fe231f6e63bc8d1598f1cba461d9e2ea7f5 -COPY --chown=ubuntu-user:kasm-user requirements.txt $HOME/requirements.txt -# Install ArduSub -RUN git clone https://github.com/ArduPilot/ardupilot.git +# Install ArduSub. Only the pinned commit is fetched: waf needs .git for +# `git rev-parse HEAD` and submodule checks, but not the project history. +RUN mkdir $HOME/ardupilot && cd $HOME/ardupilot \ + && git init -q \ + && git remote add origin https://github.com/ArduPilot/ardupilot.git \ + && git fetch -q --depth 1 origin $ARDUSUB_COMMIT \ + && git checkout -q FETCH_HEAD \ + && git submodule update --init --recursive WORKDIR $HOME/ardupilot -RUN git checkout $ARDUSUB_COMMIT -RUN git submodule update --init --recursive -RUN USER=kasm-user Tools/environment_install/install-prereqs-ubuntu.sh -y -RUN pip3 install -r $HOME/requirements.txt +# DO_AP_STM_ENV=0 skips the STM32 firmware toolchain; SITL builds with the host g++. +RUN USER=kasm-user DO_AP_STM_ENV=0 Tools/environment_install/install-prereqs-ubuntu.sh -y \ + && sudo rm -rf /var/lib/apt/lists/* $HOME/.cache/pip + +# Copied here rather than earlier so a pin change keeps the clone and prereqs +# layers; it must still precede the waf build, which needs the pinned empy. +COPY --chown=kasm-user:kasm-user requirements.txt $HOME/requirements.txt +RUN pip3 install --no-cache-dir -r $HOME/requirements.txt -ENV PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin:$PATH ENV PATH=$PATH:$HOME/ardupilot/Tools/autotest ENV PATH=/usr/lib/ccache:$PATH -RUN ["/bin/bash","-c","cd $HOME/ardupilot && ./waf configure && make sub"] +RUN ["/bin/bash","-c","cd $HOME/ardupilot && ./waf configure && make sub && ccache -C"] # install ardupilot gazebo plugin RUN sudo apt update && sudo apt install -y \ @@ -102,7 +111,7 @@ RUN sudo apt update && sudo apt install -y \ gstreamer1.0-plugins-bad \ gstreamer1.0-libav \ gstreamer1.0-gl \ - && sudo rm -rf /var/lib/apt/list/ + && sudo rm -rf /var/lib/apt/lists/* WORKDIR $HOME RUN git clone https://github.com/ArduPilot/ardupilot_gazebo && \ @@ -121,7 +130,20 @@ COPY --chown=kasm-user:kasm-user suave.repos $HOME/suave_ws/suave.repos WORKDIR $HOME/suave_ws/ RUN vcs import src < suave.repos --recursive +# Install suave deps from the package manifests alone, so editing sources +# does not rerun rosdep or geographiclib. RUN rm -rf $HOME/suave_ws/src/suave/ +COPY --parents --chown=kasm-user:kasm-user suave*/package.xml suave_managing/*/package.xml $HOME/suave_ws/src/suave/ + +WORKDIR $HOME/suave_ws +RUN ["/bin/bash", "-c", "source /opt/ros/humble/setup.bash \ + && sudo apt update \ + && rosdep update \ + && rosdep install --from-paths src --ignore-src -r -y \ + && sudo rm -rf /var/lib/apt/lists/* /root/.cache"] + +RUN ["/bin/bash", "-c", "sudo ./src/mavros/mavros/scripts/install_geographiclib_datasets.sh"] + COPY --chown=kasm-user:kasm-user suave/ $HOME/suave_ws/src/suave/suave/ COPY --chown=kasm-user:kasm-user suave_bringup/ $HOME/suave_ws/src/suave/suave_bringup/ COPY --chown=kasm-user:kasm-user suave_managing/ $HOME/suave_ws/src/suave/suave_managing/ @@ -135,17 +157,10 @@ COPY --chown=kasm-user:kasm-user suave_base/ $HOME/suave_ws/src/suave/suave_base COPY --chown=kasm-user:kasm-user suave_cli/ $HOME/suave_ws/src/suave/suave_cli/ COPY --chown=kasm-user:kasm-user env.sh $HOME/suave_ws/src/suave/env.sh -# Install suave deps -WORKDIR $HOME/suave_ws -RUN ["/bin/bash", "-c", "source /opt/ros/humble/setup.bash \ - && rosdep update \ - && rosdep install --from-paths src --ignore-src -r -y"] - -RUN ["/bin/bash", "-c", "sudo ./src/mavros/mavros/scripts/install_geographiclib_datasets.sh"] - # Build suave RUN ["/bin/bash", "-c", "source /opt/ros/humble/setup.bash \ && colcon build --symlink-install \ + && ccache -C \ && echo 'source ~/suave_ws/install/setup.bash' >> ~/.bashrc"] @@ -153,6 +168,10 @@ RUN sudo apt autoremove -y && sudo rm -rf /var/lib/apt/lists/ COPY --chown=kasm-user:kasm-user runner/ $HOME/suave_ws/src/suave/runner/ +# User-level pip scripts (mavproxy.py for sim_vehicle.py) must resolve in +# non-login shells too; appended so it never shadows system tools. +ENV PATH=${PATH}:${HOME}/.local/bin + # suave CLI: on PATH in every shell, including docker exec ENV SUAVE_ROOT=/home/kasm-user/suave_ws/src/suave ENV SUAVE_CLI_CONTEXT=container diff --git a/docker/dockerfile-suave-headless b/docker/dockerfile-suave-headless index aa61ae3..6e2988d 100644 --- a/docker/dockerfile-suave-headless +++ b/docker/dockerfile-suave-headless @@ -1,3 +1,4 @@ +# syntax=docker/dockerfile:1 # Use the official ROS 2 Humble base image. FROM ros:humble-ros-core-jammy @@ -59,22 +60,28 @@ WORKDIR $HOME ARG ARDUSUB_COMMIT=571e8c7bd3793fce1bc5184a2f6586feb8a616e5 ARG ARDUPILOT_GAZEBO_COMMIT=082a0fe231f6e63bc8d1598f1cba461d9e2ea7f5 -COPY --chown=ubuntu-user:ubuntu-user requirements.txt $HOME/requirements.txt - -# Install ArduSub -RUN git clone https://github.com/ArduPilot/ardupilot.git +# Install ArduSub. Only the pinned commit is fetched: waf needs .git for +# `git rev-parse HEAD` and submodule checks, but not the project history. +RUN mkdir $HOME/ardupilot && cd $HOME/ardupilot \ + && git init -q \ + && git remote add origin https://github.com/ArduPilot/ardupilot.git \ + && git fetch -q --depth 1 origin $ARDUSUB_COMMIT \ + && git checkout -q FETCH_HEAD \ + && git submodule update --init --recursive WORKDIR $HOME/ardupilot -RUN git checkout $ARDUSUB_COMMIT -RUN git submodule update --init --recursive -RUN USER=ubuntu-user Tools/environment_install/install-prereqs-ubuntu.sh -y +# DO_AP_STM_ENV=0 skips the STM32 firmware toolchain. SITL builds with the host g++. +RUN USER=ubuntu-user DO_AP_STM_ENV=0 Tools/environment_install/install-prereqs-ubuntu.sh -y \ + && sudo rm -rf /var/lib/apt/lists/* $HOME/.cache/pip -RUN sudo pip3 install -r $HOME/requirements.txt +# Copied here rather than earlier so a pin change keeps the clone and prereqs +# layers. It must still precede the waf build, which needs the pinned empy. +COPY --chown=ubuntu-user:ubuntu-user requirements.txt $HOME/requirements.txt +RUN pip3 install --no-cache-dir -r $HOME/requirements.txt -ENV PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin:$PATH ENV PATH=$PATH:$HOME/ardupilot/Tools/autotest ENV PATH=/usr/lib/ccache:$PATH -RUN ["/bin/bash", "-c", "cd $HOME/ardupilot && ./waf configure && make sub"] +RUN ["/bin/bash", "-c", "cd $HOME/ardupilot && ./waf configure && make sub && ccache -C"] # ArduPilot Gazebo plugin dependencies RUN sudo apt-get update && sudo apt-get install -y \ @@ -100,13 +107,30 @@ RUN git clone https://github.com/ArduPilot/ardupilot_gazebo && \ ENV GZ_SIM_SYSTEM_PLUGIN_PATH=$HOME/ardupilot_gazebo/build ENV GZ_SIM_RESOURCE_PATH=$HOME/ardupilot_gazebo/models:$HOME/ardupilot_gazebo/worlds -# Import external dependencies from suave.repos, then copy this checkout. +# Import external dependencies from suave.repos. RUN mkdir -p $HOME/suave_ws/src COPY --chown=ubuntu-user:ubuntu-user suave.repos $HOME/suave_ws/suave.repos WORKDIR $HOME/suave_ws RUN vcs import src < suave.repos --recursive +# Resolve dependencies from the package manifests alone, so editing sources +# does not rerun rosdep, geographiclib or pip. RUN rm -rf $HOME/suave_ws/src/suave && mkdir -p $HOME/suave_ws/src/suave +COPY --parents --chown=ubuntu-user:ubuntu-user suave*/package.xml suave_managing/*/package.xml $HOME/suave_ws/src/suave/ + +RUN ["/bin/bash", "-c", "source /opt/ros/humble/setup.bash \ + && sudo apt update \ + && rosdep update \ + && rosdep install --from-paths src --ignore-src -r -y \ + && sudo rm -rf /var/lib/apt/lists/ /root/.cache"] + +RUN ["/bin/bash", "-c", "sudo ./src/mavros/mavros/scripts/install_geographiclib_datasets.sh"] + +# ArduPilot installs a newer user-local flake8 which is incompatible with the +# Ubuntu Jammy flake8 plugins used by the ROS 2 Humble lint environment. +RUN pip3 install --no-cache-dir flake8==4.0.1 + +# Copy this checkout. COPY --chown=ubuntu-user:ubuntu-user suave/ $HOME/suave_ws/src/suave/suave/ COPY --chown=ubuntu-user:ubuntu-user suave_bringup/ $HOME/suave_ws/src/suave/suave_bringup/ COPY --chown=ubuntu-user:ubuntu-user suave_managing/ $HOME/suave_ws/src/suave/suave_managing/ @@ -121,26 +145,17 @@ COPY --chown=ubuntu-user:ubuntu-user suave_base/ $HOME/suave_ws/src/suave/suave_ COPY --chown=ubuntu-user:ubuntu-user suave_cli/ $HOME/suave_ws/src/suave/suave_cli/ COPY --chown=ubuntu-user:ubuntu-user env.sh $HOME/suave_ws/src/suave/env.sh -RUN ["/bin/bash", "-c", "source /opt/ros/humble/setup.bash \ - && sudo apt update \ - && rosdep update \ - && rosdep install --from-paths src --ignore-src -r -y \ - && sudo rm -rf /var/lib/apt/lists/"] - -RUN ["/bin/bash", "-c", "sudo ./src/mavros/mavros/scripts/install_geographiclib_datasets.sh"] - -RUN pip3 install -r $HOME/requirements.txt - -# ArduPilot installs a newer user-local flake8 which is incompatible with the -# Ubuntu Jammy flake8 plugins used by the ROS 2 Humble lint environment. -RUN pip3 install flake8==4.0.1 - RUN ["/bin/bash", "-c", "source /opt/ros/humble/setup.bash \ && colcon build --symlink-install \ + && ccache -C \ && echo 'source ~/suave_ws/install/setup.bash' >> ~/.bashrc"] RUN sudo apt autoremove -y && sudo rm -rf /var/lib/apt/lists/ +# User-level pip scripts (mavproxy.py for sim_vehicle.py) must resolve in +# non-login shells too; appended so it never shadows system tools. +ENV PATH=${PATH}:${HOME}/.local/bin + # suave CLI: on PATH in every shell, including docker exec ENV SUAVE_ROOT=/home/ubuntu-user/suave_ws/src/suave ENV SUAVE_CLI_CONTEXT=container