Skip to content

Commit da24cee

Browse files
Add Dockerfile and GitHub Actions workflow for building AOC Docker images (#1)
* Add Dockerfile and GitHub Actions workflow for building AOC Docker images * Add GitHub Actions workflow for building AOC Docker images with multiarch support * Update Docker build workflow to enable sequential builds and dynamic architecture support * Add CUDA Dockerfile and update build workflow for CUDA support * Refactor Docker build configuration to use ROS_DISTRO variable for tagging and installation * Add ROS installation and setup commands to CUDA Dockerfile * Add ROS_DISTRO argument and environment variables to CUDA Dockerfile * Add ARG declarations for BASE_IMAGE and ROS_DISTRO in Dockerfiles * Add CUDA Dockerfile stages for base and desktop images with ROS support * Comment out cache-from and cache-to lines in Docker build configuration * Move python3-rosdep installation to the correct stage in Dockerfile * Add target specification for Docker build stage in workflow * Add additional CUDA Dockerfile stages for base and desktop images with ROS support * Uncomment cache-from and cache-to lines in Docker build configuration * Initialize rosdep before updating in Dockerfile * Add support for ROS Jazzy in Docker build configuration * Refactor Docker build configuration by removing unused desktop stage and updating image descriptions * Add reusable Docker image build workflow and CUDA desktop Dockerfile * Add outputs section for image digest in Docker build workflow * Reorder Docker build steps to ensure proper setup of buildx before building and pushing the image * Fix Dockerfile syntax for ros installation * chore: update from ros_dist to ros_distro added to readme description of images produced * feat: add non root `ros` user --------- Co-authored-by: Josh Cooper <joshua@joshuacooper.co.uk>
1 parent 5d303c6 commit da24cee

File tree

7 files changed

+277
-1
lines changed

7 files changed

+277
-1
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Build a single Docker image (reusable)
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
base_image:
7+
description: The FROM base image
8+
required: true
9+
type: string
10+
push_image:
11+
description: Image name on the LCAS registry
12+
required: true
13+
type: string
14+
ros_distro:
15+
required: true
16+
type: string
17+
dockerfile:
18+
required: true
19+
type: string
20+
architectures:
21+
required: true
22+
type: string
23+
outputs:
24+
digest:
25+
description: Image digest from the build
26+
value: ${{ jobs.build.outputs.digest }}
27+
secrets:
28+
LCAS_REGISTRY_PUSHER:
29+
required: true
30+
LCAS_REGISTRY_TOKEN:
31+
required: true
32+
33+
jobs:
34+
build:
35+
runs-on: [lcas, qemu]
36+
outputs:
37+
digest: ${{ steps.build.outputs.digest }}
38+
steps:
39+
- uses: actions/setup-node@v4
40+
- uses: actions/checkout@v3
41+
- run: echo "BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV
42+
43+
- uses: docker/login-action@v3
44+
with:
45+
registry: lcas.lincoln.ac.uk
46+
username: ${{ secrets.LCAS_REGISTRY_PUSHER }}
47+
password: ${{ secrets.LCAS_REGISTRY_TOKEN }}
48+
49+
- name: Docker meta
50+
id: meta
51+
uses: docker/metadata-action@v5
52+
with:
53+
flavor: latest=false
54+
labels: |
55+
org.opencontainers.image.description=AOC Docker Image (${{ inputs.push_image }}, ${{ inputs.ros_distro }})
56+
org.opencontainers.image.authors=L-CAS Team
57+
images: lcas.lincoln.ac.uk/${{ inputs.push_image }}
58+
tags: |
59+
type=raw,value=${{ inputs.ros_distro }}-staging
60+
type=raw,enable=${{ github.event_name != 'pull_request' }},value=${{ inputs.ros_distro }}-latest
61+
type=ref,enable=${{ github.event_name != 'pull_request' }},event=branch,prefix=${{ inputs.ros_distro }}-
62+
type=semver,pattern={{version}},prefix=${{ inputs.ros_distro }}-
63+
type=semver,pattern={{major}}.{{minor}},prefix=${{ inputs.ros_distro }}-
64+
type=semver,pattern={{major}},prefix=${{ inputs.ros_distro }}-
65+
66+
- uses: docker/setup-buildx-action@v3
67+
68+
- name: Build and push
69+
id: build
70+
uses: docker/build-push-action@v6
71+
with:
72+
context: ./docker
73+
file: ./${{ inputs.dockerfile }}
74+
platforms: ${{ inputs.architectures }}
75+
push: true
76+
cache-from: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ inputs.push_image }}:${{ inputs.ros_distro }}
77+
cache-to: type=registry,ref=lcas.lincoln.ac.uk/cache/${{ inputs.push_image }}:${{ inputs.ros_distro }},mode=max
78+
tags: ${{ steps.meta.outputs.tags }}
79+
labels: ${{ steps.meta.outputs.labels }}
80+
build-args: |
81+
BASE_IMAGE=${{ inputs.base_image }}
82+
ROS_DISTRO=${{ inputs.ros_distro }}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Build AOC Docker Images
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
tags: [ '*' ]
7+
pull_request:
8+
branches: [ main ]
9+
workflow_dispatch:
10+
11+
jobs:
12+
13+
# ── Level 0: no dependencies ──────────────────────────────────────────────
14+
15+
ros-humble:
16+
uses: ./.github/workflows/_build-image.yaml
17+
with:
18+
base_image: ros:humble
19+
push_image: ros
20+
ros_distro: humble
21+
dockerfile: base.dockerfile
22+
architectures: linux/amd64,linux/arm64
23+
secrets: inherit
24+
25+
ros-jazzy:
26+
uses: ./.github/workflows/_build-image.yaml
27+
with:
28+
base_image: ros:jazzy
29+
push_image: ros
30+
ros_distro: jazzy
31+
dockerfile: base.dockerfile
32+
architectures: linux/amd64,linux/arm64
33+
secrets: inherit
34+
35+
ros-cuda-humble:
36+
uses: ./.github/workflows/_build-image.yaml
37+
with:
38+
base_image: nvidia/cuda:11.8.0-runtime-ubuntu22.04
39+
push_image: ros_cuda
40+
ros_distro: humble
41+
dockerfile: cuda.dockerfile
42+
architectures: linux/amd64
43+
secrets: inherit
44+
45+
ros-cuda-jazzy:
46+
uses: ./.github/workflows/_build-image.yaml
47+
with:
48+
base_image: nvidia/cuda:12.6.3-cudnn-devel-ubuntu24.04
49+
push_image: ros_cuda
50+
ros_distro: jazzy
51+
dockerfile: cuda.dockerfile
52+
architectures: linux/amd64
53+
secrets: inherit
54+
55+
# ── Level 1: base_image is the exact digest from level 0 ─────────────────
56+
57+
ros-cuda-desktop-humble:
58+
needs: ros-cuda-humble
59+
uses: ./.github/workflows/_build-image.yaml
60+
with:
61+
# Digest is immutable — no staging tag, no race condition, no cleanup
62+
base_image: lcas.lincoln.ac.uk/ros_cuda@${{ needs.ros-cuda-humble.outputs.digest }}
63+
push_image: ros_cuda_desktop
64+
ros_distro: humble
65+
dockerfile: cuda_desktop.dockerfile
66+
architectures: linux/amd64
67+
secrets: inherit
68+
69+
ros-cuda-desktop-jazzy:
70+
needs: ros-cuda-jazzy
71+
uses: ./.github/workflows/_build-image.yaml
72+
with:
73+
base_image: lcas.lincoln.ac.uk/ros_cuda@${{ needs.ros-cuda-jazzy.outputs.digest }}
74+
push_image: ros_cuda_desktop
75+
ros_distro: jazzy
76+
dockerfile: cuda_desktop.dockerfile
77+
architectures: linux/amd64
78+
secrets: inherit

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
# aoc_container_base
2-
A repository of verstile ROS-enabled Docker containers
2+
3+
A repository of verstile ROS-enabled Docker containers, orginally developed as apart of the [Agri-OpenCore (AOC) project](https://agri-opencore.org).
4+
5+
| Container Name | Tags | Purpose |
6+
| ------------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
7+
| `lcas.lincoln.ac.uk/ros` | { `humble`, `jazzy` } | Base ROS Container, the minimal environment you need for ROS |
8+
| `lcas.lincoln.ac.uk/ros_cuda` | { `humble`, `jazzy` } | ROS + Nvidia. When you need to use a GPU in your ROS environment for either better quality simulation or AI workloads. |
9+
| `lcas.lincoln.ac.uk/ros_cuda_desktop` | { `humble`, `jazzy` } | ROS + Nvidia + Packages. Installs the `ros-{distro}-desktop` varient so there is the full ROS stack available. |

base.dockerfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
ARG BASE_IMAGE=ros:humble
2+
ARG ROS_DISTRO=humble
3+
4+
FROM ${BASE_IMAGE} AS base
5+
ARG BASE_IMAGE
6+
ARG ROS_DISTRO
7+
8+
ENV BASE_IMAGE=${BASE_IMAGE}
9+
ENV ROS_DISTRO=${ROS_DISTRO}
10+
11+
ENV DEBIAN_FRONTEND=noninteractive
12+
13+
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
14+
build-essential \
15+
cmake \
16+
git \
17+
curl \
18+
wget \
19+
unzip \
20+
ros-${ROS_DISTRO}-ros-base \
21+
&& rm -rf /var/lib/apt/lists/*
22+
23+
RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep update
24+
25+
ARG USERNAME=ros
26+
ARG USER_UID=1001
27+
ARG USER_GID=$USER_UID
28+
29+
# Create a non-root user
30+
RUN groupadd --gid $USER_GID $USERNAME \
31+
&& useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
32+
# Add sudo support for the non-root user
33+
&& apt-get update \
34+
&& apt-get install -y --no-install-recommends sudo \
35+
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\
36+
&& chmod 0440 /etc/sudoers.d/$USERNAME \
37+
&& rm -rf /var/lib/apt/lists/*
38+
39+

cuda.dockerfile

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
ARG BASE_IMAGE=nvidia/cuda:11.8.0-runtime-ubuntu22.04
2+
ARG ROS_DISTRO=humble
3+
4+
5+
###########################################
6+
FROM ${BASE_IMAGE} AS base
7+
ARG BASE_IMAGE
8+
ARG ROS_DISTRO
9+
10+
ENV BASE_IMAGE=${BASE_IMAGE}
11+
ENV ROS_DISTRO=${ROS_DISTRO}
12+
13+
ENV DEBIAN_FRONTEND=noninteractive
14+
15+
# Install language
16+
RUN apt-get update ; \
17+
apt-get upgrade -y && \
18+
apt-get install -y --no-install-recommends \
19+
locales \
20+
curl \
21+
gnupg2 \
22+
lsb-release \
23+
git \
24+
nano \
25+
python3-setuptools \
26+
software-properties-common \
27+
wget \
28+
tzdata \
29+
&& locale-gen en_US.UTF-8 \
30+
&& update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 \
31+
&& rm -rf /var/lib/apt/lists/*
32+
ENV LANG=en_US.UTF-8
33+
34+
RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
35+
36+
# Prepare ROS2
37+
RUN add-apt-repository universe \
38+
&& curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg \
39+
&& 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
40+
41+
42+
RUN apt-get update && apt-get install -y --no-install-recommends \
43+
ros-${ROS_DISTRO}-ros-base \
44+
python3-rosdep \
45+
&& rm -rf /var/lib/apt/lists/*
46+
47+
RUN . /opt/ros/${ROS_DISTRO}/setup.sh && rosdep init && rosdep update
48+
49+
ARG USERNAME=ros
50+
ARG USER_UID=1001
51+
ARG USER_GID=$USER_UID
52+
53+
# Create a non-root user
54+
RUN groupadd --gid $USER_GID $USERNAME \
55+
&& useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
56+
# Add sudo support for the non-root user
57+
&& apt-get update \
58+
&& apt-get install -y --no-install-recommends sudo \
59+
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\
60+
&& chmod 0440 /etc/sudoers.d/$USERNAME \
61+
&& rm -rf /var/lib/apt/lists/*
62+

cuda_desktop.dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
ARG BASE_IMAGE
2+
3+
###########################################
4+
FROM ${BASE_IMAGE} AS base
5+
6+
RUN apt-get update && apt-get install -y --no-install-recommends \
7+
ros-${ROS_DISTRO}-desktop \
8+
&& rm -rf /var/lib/apt/lists/*

docker/.dockerignore

Whitespace-only changes.

0 commit comments

Comments
 (0)