Skip to content

Container Images ​

CobaltCore builds its own OCI-compliant container images for all OpenStack services. These images are lightweight, reproducible, and support fast patching without repository forks.

Design Goals ​

GoalImplementation
Build specific versionsBranch, tag, or commit SHA as build input (see Versioning)
Lightweight imagesMulti-stage builds, only runtime dependencies in the final image
Fast buildsuv instead of pip, layer caching, bind mounts (see Build Pipeline)
Fast patchingpatches/<service>/<release>/ directory with git apply, no fork required (see Patching)
Multi-release supportA single C5C3 branch manages multiple OpenStack releases simultaneously
Library patchingConstraint overrides and patches at the dependency level (see Patching — Library Patches)
Supply chain transparencySigned SBOM (CycloneDX) attested to each image via Sigstore (see SBOM)

Image Hierarchy ​

text
┌─────────────────────────────────────────────────────────────────┐
│                       Image Hierarchy                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ubuntu:noble (24.04 LTS)                                       │
│       │                                                         │
│       ├──▶ c5c3/python-base:latest                              │
│       │    ├── Python 3.12, runtime libraries                   │
│       │    ├── PATH=/var/lib/openstack/bin:$PATH                │
│       │    └── openstack user (UID/GID 42424, shared)           │
│       │         │                                               │
│       │         └──▶ c5c3/<service>  (final runtime image)      │
│       │              ├── COPY --from=build /var/lib/openstack   │
│       │              └── Service-specific system packages       │
│       │                                                         │
│       └──▶ c5c3/venv-builder:latest                             │
│            ├── Build dependencies (gcc, python3-dev, libssl-dev)│
│            ├── uv 0.10.9 (Python package manager)               │
│            └── Common pre-installed packages (no constraints)   │
│                 │                                               │
│                 └──▶ Build stage (discarded)                    │
│                      └── Compiles venv into                     │
│                         /var/lib/openstack                      │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Key principle: The venv builder contains all build dependencies (compilers, header files) but is never included in the final image. Only the compiled virtual environment (/var/lib/openstack) is copied via COPY --from=build into the lightweight runtime image.

Comparison of Existing Approaches ​

The C5C3 strategy is based on an analysis of OpenStack LOCI and Vexxhost Atmosphere:

AspectLOCIAtmosphereC5C3
Dockerfile structureSingle generic Dockerfile for all servicesPer-service repos with own DockerfilePer-service Dockerfile in monorepo
Python installerpip + pre-built wheelsuv (Rust-based)uv (Rust-based)
Dependency strategySeparate requirements image with wheelsupper-constraints.txt + uv directlyupper-constraints.txt + uv directly
Base imageUbuntu JammyMulti-distro (Ubuntu, Debian, Rocky)Ubuntu Noble (24.04 LTS)
Source code in buildgit clone inside DockerfileBuild context (bind mount from CI)Build context (bind mount from CI)
PatchingNo built-in mechanismpatches/ directory with git applypatches/ + library patches + constraint overrides
Library patchingNot supportedNot explicitConstraint overrides + library patches
Multi-archExperimentalNative (amd64 + arm64)Native (amd64 + arm64)
CI/CDZuul (OpenDev)GitHub Actions + Depot.devGitHub Actions
VersioningBuild args (PROJECT_REF)Branch-per-release + commit SHA pinsOwn version scheme + per-release refs (branch, tag, or SHA)
Automated updatesNoneRenovate BotRenovate Bot

Why Not LOCI? ​

  • No patching mechanism: Patches require repository forks or child images
  • Slow builds: pip + pre-built wheels instead of uv
  • Monolithic approach: A single generic Dockerfile for all services prevents service-specific optimizations
  • No library patching: Dependencies cannot be patched individually

What We Adopt from Atmosphere ​

  • uv as package manager: Dramatically faster builds
  • Build context pattern: Source code is checked out via CI and passed as a build context, not cloned inside the Dockerfile
  • Structured patching: patches/ directory with git format-patch / git apply
  • Source reference pinning: Reproducible builds through branch, tag, or commit SHA references

What C5C3 Does Differently ​

  • Multi-release per branch: A single C5C3 branch manages images for multiple OpenStack releases (e.g., 2025.2 and 2025.1), unlike Atmosphere which uses one branch per release
  • Release-scoped patches: Patches are organized as patches/<service>/<release>/, allowing different patches per OpenStack release within the same C5C3 branch
  • Library patching: Explicit support for patches at the dependency level (e.g., oslo.messaging, python-novaclient)
  • Constraint overrides: Targeted version pin changes for individual libraries, scoped per release
  • Monorepo structure: Dockerfiles live in the c5c3/forge monorepo, not in separate repos per service
  • Focus on Ubuntu Noble: A single base image instead of multi-distro to reduce complexity

Container Registry ​

text
ghcr.io/c5c3/<service>:<tag>

Tag schema (service images):

Tag formatExamplePropertyUsage
<version>-p<N>-<branch>-<sha>28.0.0-p0-main-a1b2c3dImmutablePrimary tag — always pushed
<upstream-version>28.0.0MutablePushed on main branch only (see Versioning)
<short-sha>a1b2c3dImmutableAlways pushed

Tag schema (base images):

Tag formatExamplePropertyUsage
latestpython-base:latestMutablePoints to the most recent build
<commit-sha>python-base:<sha>ImmutableFull commit SHA, pushed alongside latest

Currently integrated services:

ComponentUpstream VersionImageStatus
Keystone28.0.0ghcr.io/c5c3/keystone:28.0.0Built by CI
Nova—ghcr.io/c5c3/novaDockerfile exists, not yet in build matrix
Neutron—ghcr.io/c5c3/neutronDockerfile exists, not yet in build matrix
Glance—ghcr.io/c5c3/glanceDockerfile exists, not yet in build matrix
Cinder—ghcr.io/c5c3/cinderDockerfile exists, not yet in build matrix
Placement—ghcr.io/c5c3/placementDockerfile exists, not yet in build matrix

Note: Infrastructure services (Memcached, MariaDB, RabbitMQ, Valkey) use upstream container images directly and are not built by C5C3. They are managed by their respective operators (see Infrastructure Service Operators).

Note: OVN and OVS require a separate C-source build pipeline that has not yet been implemented.

Further Reading ​

  • Build Pipeline — Multi-stage builds, Dockerfile structure, GitHub Actions
  • Versioning — Branch strategy, tag schema, automated updates
  • Patching — Service patches, library patches, constraint overrides
  • SBOM — Software Bill of Materials, signing, attestation, regulatory compliance