From 39d0b032e072763e96028b4350f2e89b436b9f90 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 11:30:57 +0000 Subject: [PATCH 01/24] Add Dockerfile and GitHub Actions workflow for building AOC Docker images --- base.dockerfile | 16 +++++ docker/.dockerignore | 0 github/workflows/docker-build-and-push.yaml | 79 +++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 base.dockerfile create mode 100644 docker/.dockerignore create mode 100644 github/workflows/docker-build-and-push.yaml diff --git a/base.dockerfile b/base.dockerfile new file mode 100644 index 0000000..8191798 --- /dev/null +++ b/base.dockerfile @@ -0,0 +1,16 @@ +ARG BASE_IMAGE=ros:humble +FROM ${BASE_IMAGE} AS base + +ENV BASE_IMAGE=${BASE_IMAGE} + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get upgrade -y && apt-get install -y \ + build-essential \ + cmake \ + git \ + curl \ + wget \ + unzip + +RUN rosdep init && rosdep update \ No newline at end of file diff --git a/docker/.dockerignore b/docker/.dockerignore new file mode 100644 index 0000000..e69de29 diff --git a/github/workflows/docker-build-and-push.yaml b/github/workflows/docker-build-and-push.yaml new file mode 100644 index 0000000..ab17e81 --- /dev/null +++ b/github/workflows/docker-build-and-push.yaml @@ -0,0 +1,79 @@ +name: Build AOC Docker Images + +on: + push: + branches: [ main ] + tags: + - '*' + pull_request: + branches: [ main ] + + workflow_dispatch: + +jobs: + build: + runs-on: + - lcas + - qemu + strategy: + fail-fast: false + matrix: + include: + - base_image: ros:humble + push_image: ros + push_tag_prefix: humble + dockerfile: base.dockerfile + + steps: + - name: Node Js + uses: actions/setup-node@v4 + - uses: actions/checkout@v3 + - name: What + run: echo "BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV + - name: Docker Login LCAS + uses: docker/login-action@v3 + with: + # Server address of Docker registry. If not set then will default to Docker Hub + registry: lcas.lincoln.ac.uk + # Username used to log against the Docker registry + username: ${{ secrets.LCAS_REGISTRY_PUSHER }} + # Password or personal access token used to log against the Docker registry + password: ${{ secrets.LCAS_REGISTRY_TOKEN }} + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + flavor: | + latest=false + labels: | + org.opencontainers.image.description=AOC Docker Image (flavour: ${{ matrix.push_tag }}, multiarch) + org.opencontainers.image.authors=L-CAS Team + # list of Docker images to use as base name for tags + images: | + lcas.lincoln.ac.uk/${{ matrix.push_image }} + # generate Docker tags based on the following events/attributes + tags: | + type=raw,value=${{ matrix.push_tag_prefix }}-staging + type=raw,enable=${{ github.event_name != 'pull_request' }},value=${{ matrix.push_tag_prefix }}-latest + type=ref,enable=${{ github.event_name != 'pull_request' }},event=branch,prefix=${{ matrix.push_tag_prefix }}- + type=semver,pattern={{version}},prefix=${{ matrix.push_tag_prefix }}- + type=semver,pattern={{major}}.{{minor}},prefix=${{ matrix.push_tag_prefix }}- + type=semver,pattern={{major}},prefix=${{ matrix.push_tag_prefix }}- + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker Image + uses: docker/build-push-action@v6 + with: + context: ./docker + file: ./${{ matrix.dockerfile }} + platforms: linux/amd64,linux/arm64 + push: true + cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.push_tag_prefix }} + cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.push_tag_prefix }},mode=max + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + BASE_IMAGE=${{ matrix.base_image }} From 6400cd7c9f7c57fc6d68120d2fbae91a991006d6 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 11:32:35 +0000 Subject: [PATCH 02/24] Add GitHub Actions workflow for building AOC Docker images with multiarch support --- {github => .github}/workflows/docker-build-and-push.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {github => .github}/workflows/docker-build-and-push.yaml (100%) diff --git a/github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml similarity index 100% rename from github/workflows/docker-build-and-push.yaml rename to .github/workflows/docker-build-and-push.yaml From b3e9a40b7b94feb927fce50c20cadf693834bc17 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 11:36:17 +0000 Subject: [PATCH 03/24] Update Docker build workflow to enable sequential builds and dynamic architecture support --- .github/workflows/docker-build-and-push.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index ab17e81..9bf0f77 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -16,13 +16,16 @@ jobs: - lcas - qemu strategy: - fail-fast: false + fail-fast: true + # make sure we build them sequentially to maximise cache hits + max-parallel: 1 matrix: include: - base_image: ros:humble push_image: ros push_tag_prefix: humble dockerfile: base.dockerfile + architectures: linux/amd64,linux/arm64 steps: - name: Node Js @@ -69,7 +72,7 @@ jobs: with: context: ./docker file: ./${{ matrix.dockerfile }} - platforms: linux/amd64,linux/arm64 + platforms: ${{ matrix.architectures }} push: true cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.push_tag_prefix }} cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.push_tag_prefix }},mode=max From 7f2808b19d0f29bc88b2e4e525f92a9905ba22bf Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 11:42:35 +0000 Subject: [PATCH 04/24] Add CUDA Dockerfile and update build workflow for CUDA support --- .github/workflows/docker-build-and-push.yaml | 9 +++++- base.dockerfile | 2 +- cuda.dockerfile | 34 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 cuda.dockerfile diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index 9bf0f77..b65e4df 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -26,7 +26,14 @@ jobs: push_tag_prefix: humble dockerfile: base.dockerfile architectures: linux/amd64,linux/arm64 - + + - base_image: nvidia/cuda:11.8.0-runtime-ubuntu22.04 + push_image: ros_cuda + push_tag_prefix: humble + dockerfile: cuda.dockerfile + architectures: linux/amd64 + + steps: - name: Node Js uses: actions/setup-node@v4 diff --git a/base.dockerfile b/base.dockerfile index 8191798..b377b35 100644 --- a/base.dockerfile +++ b/base.dockerfile @@ -13,4 +13,4 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y \ wget \ unzip -RUN rosdep init && rosdep update \ No newline at end of file +RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep update \ No newline at end of file diff --git a/cuda.dockerfile b/cuda.dockerfile new file mode 100644 index 0000000..e09d523 --- /dev/null +++ b/cuda.dockerfile @@ -0,0 +1,34 @@ +ARG BASE_IMAGE=nvidia/cuda:11.8.0-runtime-ubuntu22.04 + +########################################### +FROM ${BASE_IMAGE} AS base + +ENV DEBIAN_FRONTEND=noninteractive + +# Install language +RUN apt-get update ; \ + apt-get upgrade -y && \ + apt-get install -y --no-install-recommends \ + locales \ + curl \ + gnupg2 \ + lsb-release \ + git \ + nano \ + python3-setuptools \ + software-properties-common \ + wget \ + tzdata \ + && locale-gen en_US.UTF-8 \ + && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 \ + && rm -rf /var/lib/apt/lists/* +ENV LANG=en_US.UTF-8 + +RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg + +# Prepare ROS2 +RUN add-apt-repository universe \ + && curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null + + From 6e0c408e8f7e05e3077e580e49fecde38c324d4d Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 11:44:20 +0000 Subject: [PATCH 05/24] Refactor Docker build configuration to use ROS_DISTRO variable for tagging and installation --- .github/workflows/docker-build-and-push.yaml | 21 ++++++++++---------- base.dockerfile | 7 ++++++- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index b65e4df..093c215 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -23,13 +23,13 @@ jobs: include: - base_image: ros:humble push_image: ros - push_tag_prefix: humble + ros_dist: humble dockerfile: base.dockerfile architectures: linux/amd64,linux/arm64 - base_image: nvidia/cuda:11.8.0-runtime-ubuntu22.04 push_image: ros_cuda - push_tag_prefix: humble + ros_dist: humble dockerfile: cuda.dockerfile architectures: linux/amd64 @@ -64,12 +64,12 @@ jobs: lcas.lincoln.ac.uk/${{ matrix.push_image }} # generate Docker tags based on the following events/attributes tags: | - type=raw,value=${{ matrix.push_tag_prefix }}-staging - type=raw,enable=${{ github.event_name != 'pull_request' }},value=${{ matrix.push_tag_prefix }}-latest - type=ref,enable=${{ github.event_name != 'pull_request' }},event=branch,prefix=${{ matrix.push_tag_prefix }}- - type=semver,pattern={{version}},prefix=${{ matrix.push_tag_prefix }}- - type=semver,pattern={{major}}.{{minor}},prefix=${{ matrix.push_tag_prefix }}- - type=semver,pattern={{major}},prefix=${{ matrix.push_tag_prefix }}- + type=raw,value=${{ matrix.ros_dist }}-staging + type=raw,enable=${{ github.event_name != 'pull_request' }},value=${{ matrix.ros_dist }}-latest + type=ref,enable=${{ github.event_name != 'pull_request' }},event=branch,prefix=${{ matrix.ros_dist }}- + type=semver,pattern={{version}},prefix=${{ matrix.ros_dist }}- + type=semver,pattern={{major}}.{{minor}},prefix=${{ matrix.ros_dist }}- + type=semver,pattern={{major}},prefix=${{ matrix.ros_dist }}- - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -81,9 +81,10 @@ jobs: file: ./${{ matrix.dockerfile }} platforms: ${{ matrix.architectures }} push: true - cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.push_tag_prefix }} - cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.push_tag_prefix }},mode=max + cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }} + cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }},mode=max tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-args: | BASE_IMAGE=${{ matrix.base_image }} + ROS_DISTRO=${{ matrix.ros_dist }} diff --git a/base.dockerfile b/base.dockerfile index b377b35..d1381d7 100644 --- a/base.dockerfile +++ b/base.dockerfile @@ -1,7 +1,10 @@ ARG BASE_IMAGE=ros:humble +ARG ROS_DISTRO=humble + FROM ${BASE_IMAGE} AS base ENV BASE_IMAGE=${BASE_IMAGE} +ENV ROS_DISTRO=${ROS_DISTRO} ENV DEBIAN_FRONTEND=noninteractive @@ -11,6 +14,8 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y \ git \ curl \ wget \ - unzip + unzip \ + ros-${ROS_DISTRO}-ros-base \ + && rm -rf /var/lib/apt/lists/* RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep update \ No newline at end of file From a1fe98dddbbbea9357cb1d491f1f238303593bf4 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 12:06:32 +0000 Subject: [PATCH 06/24] Add ROS installation and setup commands to CUDA Dockerfile --- base.dockerfile | 3 ++- cuda.dockerfile | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/base.dockerfile b/base.dockerfile index d1381d7..ee15977 100644 --- a/base.dockerfile +++ b/base.dockerfile @@ -18,4 +18,5 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y \ ros-${ROS_DISTRO}-ros-base \ && rm -rf /var/lib/apt/lists/* -RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep update \ No newline at end of file +RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep update + diff --git a/cuda.dockerfile b/cuda.dockerfile index e09d523..777155c 100644 --- a/cuda.dockerfile +++ b/cuda.dockerfile @@ -32,3 +32,8 @@ RUN add-apt-repository universe \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null +RUN apt-get update && apt-get install -y --no-install-recommends \ + ros-${ROS_DISTRO}-ros-base \ + && rm -rf /var/lib/apt/lists/* + +RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep update From a16011ab729d69aeb5fd3a24771158a9b4029ae9 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 12:15:53 +0000 Subject: [PATCH 07/24] Add ROS_DISTRO argument and environment variables to CUDA Dockerfile --- cuda.dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cuda.dockerfile b/cuda.dockerfile index 777155c..89ba7fc 100644 --- a/cuda.dockerfile +++ b/cuda.dockerfile @@ -1,7 +1,12 @@ ARG BASE_IMAGE=nvidia/cuda:11.8.0-runtime-ubuntu22.04 +ARG ROS_DISTRO=humble + ########################################### FROM ${BASE_IMAGE} AS base + +ENV BASE_IMAGE=${BASE_IMAGE} +ENV ROS_DISTRO=${ROS_DISTRO} ENV DEBIAN_FRONTEND=noninteractive From 71f257b209db76678d2fea8f85090680445ca048 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 12:23:42 +0000 Subject: [PATCH 08/24] Add ARG declarations for BASE_IMAGE and ROS_DISTRO in Dockerfiles --- base.dockerfile | 2 ++ cuda.dockerfile | 2 ++ 2 files changed, 4 insertions(+) diff --git a/base.dockerfile b/base.dockerfile index ee15977..5dd6d73 100644 --- a/base.dockerfile +++ b/base.dockerfile @@ -2,6 +2,8 @@ ARG BASE_IMAGE=ros:humble ARG ROS_DISTRO=humble FROM ${BASE_IMAGE} AS base +ARG BASE_IMAGE +ARG ROS_DISTRO ENV BASE_IMAGE=${BASE_IMAGE} ENV ROS_DISTRO=${ROS_DISTRO} diff --git a/cuda.dockerfile b/cuda.dockerfile index 89ba7fc..44004b7 100644 --- a/cuda.dockerfile +++ b/cuda.dockerfile @@ -4,6 +4,8 @@ ARG ROS_DISTRO=humble ########################################### FROM ${BASE_IMAGE} AS base +ARG BASE_IMAGE +ARG ROS_DISTRO ENV BASE_IMAGE=${BASE_IMAGE} ENV ROS_DISTRO=${ROS_DISTRO} From 3f967cb8bd0c67acfe9000775f0dc9f9314d3a4d Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 12:37:09 +0000 Subject: [PATCH 09/24] Add CUDA Dockerfile stages for base and desktop images with ROS support --- .github/workflows/docker-build-and-push.yaml | 9 +++++++++ cuda.dockerfile | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index 093c215..e9a6248 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -24,12 +24,21 @@ jobs: - base_image: ros:humble push_image: ros ros_dist: humble + stage: base dockerfile: base.dockerfile architectures: linux/amd64,linux/arm64 - base_image: nvidia/cuda:11.8.0-runtime-ubuntu22.04 push_image: ros_cuda ros_dist: humble + stage: base + dockerfile: cuda.dockerfile + architectures: linux/amd64 + + - base_image: nvidia/cuda:11.8.0-runtime-ubuntu22.04 + push_image: ros_cuda_desktop + ros_dist: humble + stage: desktop dockerfile: cuda.dockerfile architectures: linux/amd64 diff --git a/cuda.dockerfile b/cuda.dockerfile index 44004b7..61fac2c 100644 --- a/cuda.dockerfile +++ b/cuda.dockerfile @@ -26,6 +26,7 @@ RUN apt-get update ; \ software-properties-common \ wget \ tzdata \ + python3-rosdep \ && locale-gen en_US.UTF-8 \ && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 \ && rm -rf /var/lib/apt/lists/* @@ -44,3 +45,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep update + +FROM base AS desktop +RUN apt-get update && apt-get install -y --no-install-recommends \ + ros-${ROS_DISTRO}-desktop \ + && rm -rf /var/lib/apt/lists/* From 14e9331e129fe58756cb9aa083d28af2c69e49eb Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 12:41:28 +0000 Subject: [PATCH 10/24] Comment out cache-from and cache-to lines in Docker build configuration --- .github/workflows/docker-build-and-push.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index e9a6248..4c803f0 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -90,8 +90,8 @@ jobs: file: ./${{ matrix.dockerfile }} platforms: ${{ matrix.architectures }} push: true - cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }} - cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }},mode=max + #cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }} + #cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }},mode=max tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-args: | From 728dad135128d38a887dba7747a6d94f56fab8b0 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 12:42:59 +0000 Subject: [PATCH 11/24] Move python3-rosdep installation to the correct stage in Dockerfile --- cuda.dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda.dockerfile b/cuda.dockerfile index 61fac2c..942257c 100644 --- a/cuda.dockerfile +++ b/cuda.dockerfile @@ -26,7 +26,6 @@ RUN apt-get update ; \ software-properties-common \ wget \ tzdata \ - python3-rosdep \ && locale-gen en_US.UTF-8 \ && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 \ && rm -rf /var/lib/apt/lists/* @@ -42,6 +41,7 @@ RUN add-apt-repository universe \ RUN apt-get update && apt-get install -y --no-install-recommends \ ros-${ROS_DISTRO}-ros-base \ + python3-rosdep \ && rm -rf /var/lib/apt/lists/* RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep update From 3749deb3aafd1adfe5631f2a1c05ce8f099809a6 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 12:48:56 +0000 Subject: [PATCH 12/24] Add target specification for Docker build stage in workflow --- .github/workflows/docker-build-and-push.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index 4c803f0..699268e 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -90,6 +90,7 @@ jobs: file: ./${{ matrix.dockerfile }} platforms: ${{ matrix.architectures }} push: true + target: ${{ matrix.stage }} #cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }} #cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }},mode=max tags: ${{ steps.meta.outputs.tags }} From 0d530ee6add72e9f18902ed45b5daf0c474554ac Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 12:54:57 +0000 Subject: [PATCH 13/24] Add additional CUDA Dockerfile stages for base and desktop images with ROS support --- .github/workflows/docker-build-and-push.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index 699268e..ee50f9d 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -42,6 +42,20 @@ jobs: dockerfile: cuda.dockerfile architectures: linux/amd64 + - base_image: nvidia/cuda:12.6.3-cudnn-devel-ubuntu24.04 + push_image: ros_cuda + ros_dist: jazzy + stage: base + dockerfile: cuda.dockerfile + architectures: linux/amd64 + + - base_image: nvidia/cuda:12.6.3-cudnn-devel-ubuntu24.04 + push_image: ros_cuda_desktop + ros_dist: jazzy + stage: desktop + dockerfile: cuda.dockerfile + architectures: linux/amd64 + steps: - name: Node Js From c55cbf2730ff26307481f85885c35fa244436ceb Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 13:01:26 +0000 Subject: [PATCH 14/24] Uncomment cache-from and cache-to lines in Docker build configuration --- .github/workflows/docker-build-and-push.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index ee50f9d..85a53c8 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -105,8 +105,8 @@ jobs: platforms: ${{ matrix.architectures }} push: true target: ${{ matrix.stage }} - #cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }} - #cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }},mode=max + cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }} + cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }},mode=max tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-args: | From ac535ef1435ea3307093b752a34421386ef1fe3d Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 13:16:23 +0000 Subject: [PATCH 15/24] Initialize rosdep before updating in Dockerfile --- cuda.dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda.dockerfile b/cuda.dockerfile index 942257c..dbf6ef3 100644 --- a/cuda.dockerfile +++ b/cuda.dockerfile @@ -44,7 +44,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3-rosdep \ && rm -rf /var/lib/apt/lists/* -RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep update +RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep init && rosdep update FROM base AS desktop RUN apt-get update && apt-get install -y --no-install-recommends \ From 1a5d2bf35fece0ea3ff34dc3593f0e258a87a01d Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 13:21:16 +0000 Subject: [PATCH 16/24] Add support for ROS Jazzy in Docker build configuration --- .github/workflows/docker-build-and-push.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index 85a53c8..0df782d 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -21,6 +21,7 @@ jobs: max-parallel: 1 matrix: include: + # humble - base_image: ros:humble push_image: ros ros_dist: humble @@ -42,6 +43,14 @@ jobs: dockerfile: cuda.dockerfile architectures: linux/amd64 + # jazzy + - base_image: ros:jazzy + push_image: ros + ros_dist: jazzy + stage: base + dockerfile: base.dockerfile + architectures: linux/amd64,linux/arm64 + - base_image: nvidia/cuda:12.6.3-cudnn-devel-ubuntu24.04 push_image: ros_cuda ros_dist: jazzy From 37b628fbb1c0c6fdab91cd259e22c06d7f5487a3 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 13:52:59 +0000 Subject: [PATCH 17/24] Refactor Docker build configuration by removing unused desktop stage and updating image descriptions --- .github/workflows/docker-build-and-push.yaml | 22 +------------------- cuda.dockerfile | 5 ----- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index 0df782d..7454247 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -25,21 +25,12 @@ jobs: - base_image: ros:humble push_image: ros ros_dist: humble - stage: base dockerfile: base.dockerfile architectures: linux/amd64,linux/arm64 - base_image: nvidia/cuda:11.8.0-runtime-ubuntu22.04 push_image: ros_cuda ros_dist: humble - stage: base - dockerfile: cuda.dockerfile - architectures: linux/amd64 - - - base_image: nvidia/cuda:11.8.0-runtime-ubuntu22.04 - push_image: ros_cuda_desktop - ros_dist: humble - stage: desktop dockerfile: cuda.dockerfile architectures: linux/amd64 @@ -47,24 +38,14 @@ jobs: - base_image: ros:jazzy push_image: ros ros_dist: jazzy - stage: base dockerfile: base.dockerfile architectures: linux/amd64,linux/arm64 - base_image: nvidia/cuda:12.6.3-cudnn-devel-ubuntu24.04 push_image: ros_cuda ros_dist: jazzy - stage: base dockerfile: cuda.dockerfile architectures: linux/amd64 - - - base_image: nvidia/cuda:12.6.3-cudnn-devel-ubuntu24.04 - push_image: ros_cuda_desktop - ros_dist: jazzy - stage: desktop - dockerfile: cuda.dockerfile - architectures: linux/amd64 - steps: - name: Node Js @@ -89,7 +70,7 @@ jobs: flavor: | latest=false labels: | - org.opencontainers.image.description=AOC Docker Image (flavour: ${{ matrix.push_tag }}, multiarch) + org.opencontainers.image.description=AOC Docker Image (flavour: ${{ matrix.push_image }}, ${{ matrix.ros_dist }}, ${{ matrix.architectures }}) org.opencontainers.image.authors=L-CAS Team # list of Docker images to use as base name for tags images: | @@ -113,7 +94,6 @@ jobs: file: ./${{ matrix.dockerfile }} platforms: ${{ matrix.architectures }} push: true - target: ${{ matrix.stage }} cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }} cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }},mode=max tags: ${{ steps.meta.outputs.tags }} diff --git a/cuda.dockerfile b/cuda.dockerfile index dbf6ef3..7c273aa 100644 --- a/cuda.dockerfile +++ b/cuda.dockerfile @@ -45,8 +45,3 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep init && rosdep update - -FROM base AS desktop -RUN apt-get update && apt-get install -y --no-install-recommends \ - ros-${ROS_DISTRO}-desktop \ - && rm -rf /var/lib/apt/lists/* From 2e8ba15993fe78f4430b814fe16d5df8fa89f6fc Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 14:02:18 +0000 Subject: [PATCH 18/24] Add reusable Docker image build workflow and CUDA desktop Dockerfile --- .github/workflows/_build-image.yaml | 74 +++++++++ .github/workflows/docker-build-and-push.yaml | 151 ++++++++----------- cuda_desktop.dockerfile | 8 + 3 files changed, 145 insertions(+), 88 deletions(-) create mode 100644 .github/workflows/_build-image.yaml create mode 100644 cuda_desktop.dockerfile diff --git a/.github/workflows/_build-image.yaml b/.github/workflows/_build-image.yaml new file mode 100644 index 0000000..e8e85e1 --- /dev/null +++ b/.github/workflows/_build-image.yaml @@ -0,0 +1,74 @@ +name: Build a single Docker image (reusable) + +on: + workflow_call: + inputs: + base_image: + description: The FROM base image + required: true + type: string + push_image: + description: Image name on the LCAS registry + required: true + type: string + ros_dist: + required: true + type: string + dockerfile: + required: true + type: string + architectures: + required: true + type: string + secrets: + LCAS_REGISTRY_PUSHER: + required: true + LCAS_REGISTRY_TOKEN: + required: true + +jobs: + build: + runs-on: [lcas, qemu] + steps: + - uses: actions/setup-node@v4 + - uses: actions/checkout@v3 + - run: echo "BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV + + - uses: docker/login-action@v3 + with: + registry: lcas.lincoln.ac.uk + username: ${{ secrets.LCAS_REGISTRY_PUSHER }} + password: ${{ secrets.LCAS_REGISTRY_TOKEN }} + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + flavor: latest=false + labels: | + org.opencontainers.image.description=AOC Docker Image (${{ inputs.push_image }}, ${{ inputs.ros_dist }}) + org.opencontainers.image.authors=L-CAS Team + images: lcas.lincoln.ac.uk/${{ inputs.push_image }} + tags: | + type=raw,value=${{ inputs.ros_dist }}-staging + type=raw,enable=${{ github.event_name != 'pull_request' }},value=${{ inputs.ros_dist }}-latest + type=ref,enable=${{ github.event_name != 'pull_request' }},event=branch,prefix=${{ inputs.ros_dist }}- + type=semver,pattern={{version}},prefix=${{ inputs.ros_dist }}- + type=semver,pattern={{major}}.{{minor}},prefix=${{ inputs.ros_dist }}- + type=semver,pattern={{major}},prefix=${{ inputs.ros_dist }}- + + - uses: docker/setup-buildx-action@v3 + + - uses: docker/build-push-action@v6 + with: + context: ./docker + file: ./${{ inputs.dockerfile }} + platforms: ${{ inputs.architectures }} + push: true + cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ inputs.push_image }}:${{ inputs.ros_dist }} + cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ inputs.push_image }}:${{ inputs.ros_dist }},mode=max + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + BASE_IMAGE=${{ inputs.base_image }} + ROS_DISTRO=${{ inputs.ros_dist }} \ No newline at end of file diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index 7454247..75989e4 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -3,101 +3,76 @@ name: Build AOC Docker Images on: push: branches: [ main ] - tags: - - '*' + tags: [ '*' ] pull_request: branches: [ main ] - workflow_dispatch: jobs: - build: - runs-on: - - lcas - - qemu - strategy: - fail-fast: true - # make sure we build them sequentially to maximise cache hits - max-parallel: 1 - matrix: - include: - # humble - - base_image: ros:humble - push_image: ros - ros_dist: humble - dockerfile: base.dockerfile - architectures: linux/amd64,linux/arm64 - - base_image: nvidia/cuda:11.8.0-runtime-ubuntu22.04 - push_image: ros_cuda - ros_dist: humble - dockerfile: cuda.dockerfile - architectures: linux/amd64 + # ── Level 0: no dependencies ────────────────────────────────────────────── + + ros-humble: + uses: ./.github/workflows/_build-image.yaml + with: + base_image: ros:humble + push_image: ros + ros_dist: humble + dockerfile: base.dockerfile + architectures: linux/amd64,linux/arm64 + secrets: inherit + + ros-jazzy: + uses: ./.github/workflows/_build-image.yaml + with: + base_image: ros:jazzy + push_image: ros + ros_dist: jazzy + dockerfile: base.dockerfile + architectures: linux/amd64,linux/arm64 + secrets: inherit + + ros-cuda-humble: + uses: ./.github/workflows/_build-image.yaml + with: + base_image: nvidia/cuda:11.8.0-runtime-ubuntu22.04 + push_image: ros_cuda + ros_dist: humble + dockerfile: cuda.dockerfile + architectures: linux/amd64 + secrets: inherit - # jazzy - - base_image: ros:jazzy - push_image: ros - ros_dist: jazzy - dockerfile: base.dockerfile - architectures: linux/amd64,linux/arm64 + ros-cuda-jazzy: + uses: ./.github/workflows/_build-image.yaml + with: + base_image: nvidia/cuda:12.6.3-cudnn-devel-ubuntu24.04 + push_image: ros_cuda + ros_dist: jazzy + dockerfile: cuda.dockerfile + architectures: linux/amd64 + secrets: inherit - - base_image: nvidia/cuda:12.6.3-cudnn-devel-ubuntu24.04 - push_image: ros_cuda - ros_dist: jazzy - dockerfile: cuda.dockerfile - architectures: linux/amd64 - - steps: - - name: Node Js - uses: actions/setup-node@v4 - - uses: actions/checkout@v3 - - name: What - run: echo "BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV - - name: Docker Login LCAS - uses: docker/login-action@v3 - with: - # Server address of Docker registry. If not set then will default to Docker Hub - registry: lcas.lincoln.ac.uk - # Username used to log against the Docker registry - username: ${{ secrets.LCAS_REGISTRY_PUSHER }} - # Password or personal access token used to log against the Docker registry - password: ${{ secrets.LCAS_REGISTRY_TOKEN }} + # ── Level 1: base_image is the exact digest from level 0 ───────────────── - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - flavor: | - latest=false - labels: | - org.opencontainers.image.description=AOC Docker Image (flavour: ${{ matrix.push_image }}, ${{ matrix.ros_dist }}, ${{ matrix.architectures }}) - org.opencontainers.image.authors=L-CAS Team - # list of Docker images to use as base name for tags - images: | - lcas.lincoln.ac.uk/${{ matrix.push_image }} - # generate Docker tags based on the following events/attributes - tags: | - type=raw,value=${{ matrix.ros_dist }}-staging - type=raw,enable=${{ github.event_name != 'pull_request' }},value=${{ matrix.ros_dist }}-latest - type=ref,enable=${{ github.event_name != 'pull_request' }},event=branch,prefix=${{ matrix.ros_dist }}- - type=semver,pattern={{version}},prefix=${{ matrix.ros_dist }}- - type=semver,pattern={{major}}.{{minor}},prefix=${{ matrix.ros_dist }}- - type=semver,pattern={{major}},prefix=${{ matrix.ros_dist }}- + ros-cuda-desktop-humble: + needs: ros-cuda-humble + uses: ./.github/workflows/_build-image.yaml + with: + # Digest is immutable — no staging tag, no race condition, no cleanup + base_image: lcas.lincoln.ac.uk/ros_cuda@${{ needs.ros-cuda-humble.outputs.digest }} + push_image: ros_cuda_desktop + ros_dist: humble + dockerfile: cuda_desktop.dockerfile + architectures: linux/amd64 + secrets: inherit - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build Docker Image - uses: docker/build-push-action@v6 - with: - context: ./docker - file: ./${{ matrix.dockerfile }} - platforms: ${{ matrix.architectures }} - push: true - cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }} - cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ matrix.push_image }}:${{ matrix.ros_dist }},mode=max - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - build-args: | - BASE_IMAGE=${{ matrix.base_image }} - ROS_DISTRO=${{ matrix.ros_dist }} + ros-cuda-desktop-jazzy: + needs: ros-cuda-jazzy + uses: ./.github/workflows/_build-image.yaml + with: + base_image: lcas.lincoln.ac.uk/ros_cuda@${{ needs.ros-cuda-jazzy.outputs.digest }} + push_image: ros_cuda_desktop + ros_dist: jazzy + dockerfile: cuda_desktop.dockerfile + architectures: linux/amd64 + secrets: inherit \ No newline at end of file diff --git a/cuda_desktop.dockerfile b/cuda_desktop.dockerfile new file mode 100644 index 0000000..a50c615 --- /dev/null +++ b/cuda_desktop.dockerfile @@ -0,0 +1,8 @@ +ARG BASE_IMAGE + +########################################### +FROM ${BASE_IMAGE} AS base + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ros-${ROS_DISTRO}-ros-desktop \ + && rm -rf /var/lib/apt/lists/* From 6a10ecda2f25b1ee9e988d2dfb20816848aa6c98 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 14:06:07 +0000 Subject: [PATCH 19/24] Add outputs section for image digest in Docker build workflow --- .github/workflows/_build-image.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/_build-image.yaml b/.github/workflows/_build-image.yaml index e8e85e1..ef7fb39 100644 --- a/.github/workflows/_build-image.yaml +++ b/.github/workflows/_build-image.yaml @@ -20,6 +20,10 @@ on: architectures: required: true type: string + outputs: + digest: + description: Image digest from the build + value: ${{ jobs.build.outputs.digest }} secrets: LCAS_REGISTRY_PUSHER: required: true @@ -29,6 +33,8 @@ on: jobs: build: runs-on: [lcas, qemu] + outputs: + digest: ${{ steps.build.outputs.digest }} steps: - uses: actions/setup-node@v4 - uses: actions/checkout@v3 @@ -57,7 +63,9 @@ jobs: type=semver,pattern={{major}}.{{minor}},prefix=${{ inputs.ros_dist }}- type=semver,pattern={{major}},prefix=${{ inputs.ros_dist }}- - - uses: docker/setup-buildx-action@v3 + - name: Build and push + id: build + uses: docker/setup-buildx-action@v3 - uses: docker/build-push-action@v6 with: From 8d666796a40b7e03b08209b3129da510edb2b83c Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 14:10:20 +0000 Subject: [PATCH 20/24] Reorder Docker build steps to ensure proper setup of buildx before building and pushing the image --- .github/workflows/_build-image.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/_build-image.yaml b/.github/workflows/_build-image.yaml index ef7fb39..bad8c5d 100644 --- a/.github/workflows/_build-image.yaml +++ b/.github/workflows/_build-image.yaml @@ -63,11 +63,11 @@ jobs: type=semver,pattern={{major}}.{{minor}},prefix=${{ inputs.ros_dist }}- type=semver,pattern={{major}},prefix=${{ inputs.ros_dist }}- + - uses: docker/setup-buildx-action@v3 + - name: Build and push id: build - uses: docker/setup-buildx-action@v3 - - - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v6 with: context: ./docker file: ./${{ inputs.dockerfile }} From 0591fb5674cc8668148bbe706fc54ffb63af6767 Mon Sep 17 00:00:00 2001 From: Marc Hanheide Date: Mon, 16 Feb 2026 14:16:26 +0000 Subject: [PATCH 21/24] Fix Dockerfile syntax for ros installation --- cuda_desktop.dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_desktop.dockerfile b/cuda_desktop.dockerfile index a50c615..9e36983 100644 --- a/cuda_desktop.dockerfile +++ b/cuda_desktop.dockerfile @@ -4,5 +4,5 @@ ARG BASE_IMAGE FROM ${BASE_IMAGE} AS base RUN apt-get update && apt-get install -y --no-install-recommends \ - ros-${ROS_DISTRO}-ros-desktop \ + ros-${ROS_DISTRO}-desktop \ && rm -rf /var/lib/apt/lists/* From 7665cdee88d5002d9a2c3e68e0046f70a2045730 Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Mon, 16 Feb 2026 12:30:14 +0000 Subject: [PATCH 22/24] feat: add seperate display container this is the code I have been working on locally to create a display container that is **seperate** and **not ros enabled** the idea with it not being ros enabled and running on debian:trixie-slim is to keep the size of this display container down, and reduce complexity. --- display.dockerfile | 152 +++++++++++++++++++++++++++++++++++ docker/display-entrypoint.sh | 78 ++++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 display.dockerfile create mode 100644 docker/display-entrypoint.sh diff --git a/display.dockerfile b/display.dockerfile new file mode 100644 index 0000000..6ec0eeb --- /dev/null +++ b/display.dockerfile @@ -0,0 +1,152 @@ +FROM debian:trixie-slim AS base + +ARG username=aoc + +ENV DEBIAN_FRONTEND=noninteractive \ + DISPLAY=:1 \ + VNC_PORT=5900 \ + NOVNC_PORT=5801 \ + RESOLUTION=1366x768x24 + +# Install timezone +RUN ln -fs /usr/share/zoneinfo/UTC /etc/localtime \ + && export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get install -y --no-install-recommends tzdata \ + && dpkg-reconfigure --frontend noninteractive tzdata \ + && rm -rf /var/lib/apt/lists/* + +# Install packages +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + gnupg2 \ + lsb-release \ + git \ + nano \ + sudo \ + python3-setuptools \ + wget \ + libglvnd0 \ + libgl1 \ + libglx0 \ + libegl1 \ + libxext6 \ + libx11-6 \ + x11-utils \ + python3-minimal \ + python3-pip \ + python3-numpy \ + python3-venv \ + less \ + tmux \ + screen \ + unzip \ + x11-apps \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user +RUN useradd -m -s /bin/bash -G video,sudo ${username} && \ + echo "${username} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Fix /tmp/.X11-unix permissions +RUN mkdir -p /tmp/.X11-unix && \ + chmod 1777 /tmp/.X11-unix + +# Install VirtualGL +ARG TARGETARCH +ENV DEBIAN_FRONTEND=noninteractive +RUN curl -L -O https://github.com/VirtualGL/virtualgl/releases/download/3.1.1/virtualgl_3.1.1_${TARGETARCH}.deb && \ + apt-get update && \ + apt-get -y install ./virtualgl_3.1.1_${TARGETARCH}.deb && \ + rm virtualgl_3.1.1_${TARGETARCH}.deb && rm -rf /var/lib/apt/lists/* +RUN curl -L -O https://github.com/TurboVNC/turbovnc/releases/download/3.1.1/turbovnc_3.1.1_${TARGETARCH}.deb && \ + apt-get update && \ + apt-get -y install ./turbovnc_3.1.1_${TARGETARCH}.deb && \ + rm turbovnc_3.1.1_${TARGETARCH}.deb && rm -rf /var/lib/apt/lists/* +RUN addgroup --system vglusers && adduser ${username} vglusers + + +# Install noVNC +ENV NOVNC_VERSION=1.4.0 +ENV WEBSOCKETIFY_VERSION=0.10.0 + +RUN mkdir -p /usr/local/novnc && \ +curl -sSL https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.zip -o /tmp/novnc-install.zip && \ +unzip /tmp/novnc-install.zip -d /usr/local/novnc && \ +cp /usr/local/novnc/noVNC-${NOVNC_VERSION}/vnc.html /usr/local/novnc/noVNC-${NOVNC_VERSION}/index.html && \ +curl -sSL https://github.com/novnc/websockify/archive/v${WEBSOCKETIFY_VERSION}.zip -o /tmp/websockify-install.zip && \ +unzip /tmp/websockify-install.zip -d /usr/local/novnc && \ +ln -s /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION} /usr/local/novnc/noVNC-${NOVNC_VERSION}/utils/websockify && \ +rm -f /tmp/websockify-install.zip /tmp/novnc-install.zip && \ +sed -i -E 's/^python /python3 /' /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION}/run + +RUN cat < /usr/share/glvnd/egl_vendor.d/10_nvidia.json +{ + "file_format_version" : "1.0.0", + "ICD" : { + "library_path" : "libEGL_nvidia.so.0" + } +} +EOF + +FROM base AS xfce + +# Install XFCE4 +RUN apt-get update && \ + apt-get -y install \ + xfce4-session \ + xfce4-panel \ + xfdesktop4 \ + konsole \ + && rm -rf /var/lib/apt/lists/* +RUN apt-get purge -y xfce4-screensaver + +# thunar + +COPY docker/display-entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT [ "/entrypoint.sh" ] + +# Set default XFCE wallpaper -- doesnt work +# COPY aoc_wallpaper.jpg /usr/share/backgrounds/xfce/aoc_wallpaper.jpg +# RUN mkdir -p /home/${username}/.config/xfce4/xfconf/xfce-perchannel-xml && \ +# cat > /home/${username}/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml <<'EOF' +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# EOF +RUN chown -R ${username}:${username} /home/${username}/.config + +# Allow other containers to share windows into this display +RUN echo 'xhost +local: 2>/dev/null' >> ~/.bashrc + +EXPOSE 5801 + +USER ${username} +ENV HOME=/home/${username} +WORKDIR ${HOME} +RUN mkdir -p ${HOME}/.local/bin + +ENV DISPLAY=:1 +ENV TVNC_VGL=1 +ENV VGL_ISACTIVE=1 +ENV VGL_FPS=25 +ENV VGL_COMPRESS=0 +ENV VGL_DISPLAY=egl +ENV VGL_WM=1 +ENV VGL_PROBEGLX=0 +ENV LD_PRELOAD=/usr/lib/libdlfaker.so:/usr/lib/libvglfaker.so +ENV SHELL=/bin/bash \ No newline at end of file diff --git a/docker/display-entrypoint.sh b/docker/display-entrypoint.sh new file mode 100644 index 0000000..1c35c35 --- /dev/null +++ b/docker/display-entrypoint.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +echo +echo "****************************************************************************************************************************************" +echo "AOC Display container starting..." +echo "****************************************************************************************************************************************" + + +echo "starting turbovnc" +sudo rm -rf /tmp/.X1-lock /tmp/.X11-unix/X1 > /dev/null 2>&1 +screen -dmS turbovnc bash -c 'VGL_DISPLAY=egl VGL_FPS=30 /opt/TurboVNC/bin/vncserver :1 -depth 24 -noxstartup -securitytypes TLSNone,X509None,None 2>&1 | tee /tmp/vnc.log; read -p "Press any key to continue..."' +# wait for VNC to be running + +echo "waiting for display to be up" +while ! xdpyinfo -display :1 2> /dev/null > /dev/null; do + sleep .1 +done +echo "display is up" + +echo "starting xfce4" +screen -dmS xfce4 bash -c 'DISPLAY=:1 /usr/bin/xfce4-session 2>&1 | tee /tmp/xfce4.log' +while [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; do + if pgrep xfce4-session > /dev/null; then + XFCE_PID=$(pgrep xfce4-session) + export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$XFCE_PID/environ|cut -d= -f2-|tr -d '\0') + fi + sleep .1 +done +echo "xfce4 up" + +echo "starting novnc ${NOVNC_VERSION}" +screen -dmS novnc bash -c '/usr/local/novnc/noVNC-${NOVNC_VERSION}/utils/novnc_proxy --vnc localhost:5901 --listen 5801 2>&1 | tee /tmp/novnc.log' + +DISPLAY=:1 xhost +local: 2>/dev/null +echo "xhost +local: applied to :1" + +# ensure wallpaper/panels are applied; start xfdesktop if missing +( + sleep 8 + export DISPLAY=:1 + export DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" + + # start xfdesktop if not running so it can apply the wallpaper + if ! pgrep -u "$USER" xfdesktop > /dev/null 2>&1; then + xfdesktop --daemon > /dev/null 2>&1 || true + fi + + WALLPAPER="/usr/share/backgrounds/xfce/aoc_wallpaper.jpg" + + # apply wallpaper for monitor0 (add others if needed) + xfconf-query -c xfce4-desktop -np /backdrop/screen0/monitor0/image-path -t string -s "$WALLPAPER" > /dev/null 2>&1 + xfconf-query -c xfce4-desktop -np /backdrop/screen0/monitor0/last-image -t string -s "$WALLPAPER" > /dev/null 2>&1 + xfconf-query -c xfce4-desktop -np /backdrop/screen0/monitor0/workspace0/last-image -t string -s "$WALLPAPER" > /dev/null 2>&1 + xfconf-query -c xfce4-desktop -np /backdrop/screen0/monitor0/image-show -t bool -s true > /dev/null 2>&1 + + # remove secondary panel if present + xfconf-query -c xfce4-panel -p /panels/panel-2 -r > /dev/null 2>&1 || true + xfce4-panel --reload > /dev/null 2>&1 || true + + xfdesktop --reload > /dev/null 2>&1 || true +) & + +echo +echo "****************************************************************************************************************************************" +echo "Desktop ready. Open your browser at http://localhost:5801/vnc.html?autoconnect=true or another hostname and port you may have forwarded." +echo "****************************************************************************************************************************************" +echo + +echo >&2 + +# This script can either be a wrapper around arbitrary command lines, +# or it will simply exec bash if no arguments were given +if [[ $# -eq 0 ]]; then + exec "/bin/bash" +else + exec "$@" +fi + From 940098f770f1189bea24a6800b0324e6ee55b6dc Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Tue, 17 Feb 2026 14:52:02 +0000 Subject: [PATCH 23/24] ci: rename the container from `display` to `vnc` add CI building --- .github/workflows/docker-build-and-push.yaml | 10 ++++++++++ docker/{display-entrypoint.sh => vnc-entrypoint.sh} | 4 ++-- display.dockerfile => vnc.dockerfile | 8 +++++--- 3 files changed, 17 insertions(+), 5 deletions(-) rename docker/{display-entrypoint.sh => vnc-entrypoint.sh} (94%) rename display.dockerfile => vnc.dockerfile (96%) diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index f2c6942..2173e3a 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -10,6 +10,16 @@ on: jobs: + # ── VNC Container Building ──────────────────────-──────────────────────── + vnc: + uses: ./.github/workflows/_build-image.yaml + with: + base_image: debian:trixie-slim + push_image: vnc + dockerfile: vnc.dockerfile + architectures: linux/amd64,linux/arm64 + secrets: inherit + # ── Level 0: no dependencies ────────────────────────────────────────────── ros-humble: diff --git a/docker/display-entrypoint.sh b/docker/vnc-entrypoint.sh similarity index 94% rename from docker/display-entrypoint.sh rename to docker/vnc-entrypoint.sh index 1c35c35..76d9a93 100644 --- a/docker/display-entrypoint.sh +++ b/docker/vnc-entrypoint.sh @@ -2,7 +2,7 @@ echo echo "****************************************************************************************************************************************" -echo "AOC Display container starting..." +echo "AOC VNC container starting..." echo "****************************************************************************************************************************************" @@ -62,7 +62,7 @@ echo "xhost +local: applied to :1" echo echo "****************************************************************************************************************************************" -echo "Desktop ready. Open your browser at http://localhost:5801/vnc.html?autoconnect=true or another hostname and port you may have forwarded." +echo "VNC Desktop ready. Open your browser at http://localhost:5801/vnc.html?autoconnect=true or another hostname and port you may have forwarded." echo "****************************************************************************************************************************************" echo diff --git a/display.dockerfile b/vnc.dockerfile similarity index 96% rename from display.dockerfile rename to vnc.dockerfile index 6ec0eeb..7cee0fe 100644 --- a/display.dockerfile +++ b/vnc.dockerfile @@ -1,6 +1,9 @@ -FROM debian:trixie-slim AS base +ARG BASE_IMAGE=debian:trixie-slim +FROM ${BASE_IMAGE} AS base +ARG BASE_IMAGE ARG username=aoc +ENV BASE_IMAGE=${BASE_IMAGE} ENV DEBIAN_FRONTEND=noninteractive \ DISPLAY=:1 \ @@ -22,7 +25,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ gnupg2 \ lsb-release \ - git \ nano \ sudo \ python3-setuptools \ @@ -104,7 +106,7 @@ RUN apt-get purge -y xfce4-screensaver # thunar -COPY docker/display-entrypoint.sh /entrypoint.sh +COPY docker/vnc-entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT [ "/entrypoint.sh" ] From 2f6514f9ca317ab994c5b030b81f9530217af53d Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Tue, 17 Feb 2026 14:54:13 +0000 Subject: [PATCH 24/24] ci: disable requirement for ros distro, allowing for non ros builds --- .github/workflows/_build-image.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/_build-image.yaml b/.github/workflows/_build-image.yaml index ca32072..1241d02 100644 --- a/.github/workflows/_build-image.yaml +++ b/.github/workflows/_build-image.yaml @@ -12,7 +12,7 @@ on: required: true type: string ros_distro: - required: true + required: false type: string dockerfile: required: true