Skip to content

About

OpenModelica build-deps Docker Image

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

103 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenModelica build-deps Docker Images

Build, Release & Publish

The Docker images used to build and deploy OpenModelica with Jenkins.

Images are published to:

  • ghcr.io/openmodelica/build-deps (GitHub Container Registry)
  • docker.openmodelica.org/build-deps (Nexus)

Structure of the Repository

Every image lives on main, keyed by operating system and OS version rather than by OpenModelica version. Each image is a base plus optional, layered add-ons, so the heavy common tooling is built once and reused.

main
├── apt/
│   └── Dockerfile          # multi-stage: all Ubuntu + Debian versions + add-ons
├── apk/
│   └── Dockerfile          # multi-stage: Alpine Linux + add-ons
├── rpm/
│   └── Dockerfile          # multi-stage: AlmaLinux, RHEL, Fedora
├── pacman/
│   └── Dockerfile          # placeholder (not implemented yet)
└── .ci/
    ├── matrix.yml          # source of truth: which images exist
    ├── matrix.py           # matrix.yml -> CI matrix / tag lookup
    ├── lib.sh              # recipe hash + registry hash label
    ├── registry-status.sh  # does this image need building at all?
    ├── build.sh            # build one image (base + add-ons), write GHA cache
    └── publish.sh          # push + sign one image to every registry
  • Base image — one per OS/OS-version. Contains everything needed to build OpenModelica (distro packages + common tooling: TeX, Qt, Python venv, ccache, …). This is what most CI jobs use.
  • Add-on image — the base plus one thing the distro package manager can't provide or that needs a pinned version (e.g. CMake 4). Realized as an extra build stage (FROM the base stage) in the same Dockerfile, so shared layers are reused from cache.

Ubuntu and Debian share apt/Dockerfile. The DISTRO and VERSION build-args select the base image; the Qt package set is picked from ${ID}:${VERSION_ID} at build time. The base image is the full stage; each add-on is a further stage (e.g. --target cmake-4).

Each image's context, dockerfile, target, build_args and addons (add-on stage names) are declared in .ci/matrix.yml.

To add a new image, create or extend the OS's Dockerfile and list it in .ci/matrix.yml (a new version of an existing OS needs only a matrix entry).

Image naming & tags

One image repository per registry; OS, version and variant are encoded in the tag:

Tag Mutable? Meaning
ubuntu-24.04 moving Latest base image for Ubuntu 24.04
ubuntu-24.04-2.1.0 immutable Pinned base, synthesized from git tag v2.1.0
ubuntu-24.04-cmake-4 moving Latest CMake 4 add-on on the 24.04 base
ubuntu-24.04-cmake-4-2.1.0 immutable Pinned add-on, synthesized from git tag v2.1.0

Releasing is done by pushing a single repo-wide git tag v<MAJOR>.<MINOR>.<PATCH> (e.g. v2.1.0). CI synthesizes the per-image immutable Docker tags from it and publishes all images in one run. Day-to-day CI uses the moving tag; when an OpenModelica release needs a frozen environment it pins the immutable tag.

Currently provided images

OS / version Base tag Add-ons Dockerfile
Ubuntu 26.04 (Resolute) ubuntu-26.04 rust, rust-qt-wasm, rust-qt-win-x86_64, rust-qt-win-aarch64, rust-qt-mac, debug, omsimulator apt/Dockerfile
Ubuntu 24.04 (Noble) ubuntu-24.04 cmake-4, debug, omsimulator apt/Dockerfile
Ubuntu 22.04 (Jammy) ubuntu-22.04 debug, newer-qt, qt-aarch64-linux, omsimulator apt/Dockerfile
Debian 13 (Trixie) debian-13 cmake-4, debug apt/Dockerfile
Debian 12 (Bookworm) debian-12 cmake-4, debug apt/Dockerfile
Alpine 3.24 alpine-3.24 omsimulator apk/Dockerfile
AlmaLinux 10 almalinux-10 – rpm/Dockerfile
AlmaLinux 9 almalinux-9 – rpm/Dockerfile
Fedora 44 fedora-44 – rpm/Dockerfile
Fedora 43 fedora-43 – rpm/Dockerfile

Build locally

Base image — pick the distro and version with DISTRO and VERSION:

# Ubuntu
docker build --pull --no-cache \
  --target full \
  --build-arg DISTRO=ubuntu --build-arg VERSION=24.04 \
  --tag build-deps:ubuntu-24.04 \
  apt

# Debian
docker build --pull --no-cache \
  --target full \
  --build-arg DISTRO=debian --build-arg VERSION=13 --build-arg INTEL_OCL_PKGS= \
  --tag build-deps:debian-13 \
  apt

Add-on image — build the add-on's stage with --target. It reuses the base's cached layers, so it only adds the extra step:

docker build --pull \
  --target cmake-4 \
  --build-arg DISTRO=ubuntu --build-arg VERSION=24.04 \
  --tag build-deps:ubuntu-24.04-cmake-4 \
  apt

Alpine uses the separate apk/Dockerfile context. Alpine has no OpenModelica apk repo, so the build dependencies are installed directly; the only build-arg is VERSION (the Alpine release):

# Base image (the `full` stage)
docker build --pull --no-cache \
  --target full \
  --build-arg VERSION=3.24 \
  --tag build-deps:alpine-3.24 \
  apk

# OMSimulator add-on (reuses the base's cached layers)
docker build --pull \
  --target omsimulator \
  --build-arg VERSION=3.24 \
  --tag build-deps:alpine-3.24-omsimulator \
  apk

Enterprise Linux (AlmaLinux, RHEL) and Fedora share rpm/Dockerfile. DISTRO and VERSION select the base image; EPEL/CRB, Qt5/Qt6, autoconf 2.7x and gcc-toolset are picked from ID/PLATFORM_ID at build time:

# AlmaLinux
docker build --pull --no-cache \
  --target full \
  --build-arg DISTRO=almalinux --build-arg VERSION=10 \
  --tag build-deps:almalinux-10 \
  rpm

# Fedora
docker build --pull --no-cache \
  --target full \
  --build-arg DISTRO=fedora --build-arg VERSION=44 \
  --tag build-deps:fedora-44 \
  rpm

The values to pass (context, --file, --target, --build-arg) for any image are exactly its fields in .ci/matrix.yml.

CI workflow

A single workflow, build.yml, runs the whole pipeline so that a release it creates can publish in the same run (a release created with GITHUB_TOKEN cannot trigger a separate workflow):

pull request  discover ─▶ build (changed images only, no push)
push main     discover ─▶ publish ─▶ cleanup
push tag      discover ─▶ publish ─▶ release
  • build — on a pull request, builds the base + add-ons whose recipe the PR changed (no push). Unchanged images cost one registry lookup.
  • publish — builds each image once and pushes it to GHCR and Nexus from that single build, so both registries share a digest. Moving tags (<os>-<version>) are updated on every push to main, the weekly schedule, and workflow_dispatch. Immutable tags (<os>-<version>-<semver>) are pushed on a release tag, and can also be republished via workflow_dispatch when a global v<semver> is supplied. On GHCR the immutable tags are cosign-signed — only on releases (and optionally on workflow_dispatch re-publishes of a release); the moving tag of a released image points at the same digest, so it verifies with the same signature.
  • release — on a repo-wide release tag, creates/updates the GitHub Release once every image has been published.

Only building what changed

Every published image carries the hash of the recipe it was built from as the org.openmodelica.build-deps.hash label — the same label apt-build's Jenkinsfile uses for its own build-deps images. The hash covers the build-args, the stage that is built, the instructions building that stage would run, and the rest of the build context, so it changes exactly when the image would come out different.

Before building anything, a job reads that label from the registry and skips the image when every tag it would push already matches, so a change to one Dockerfile does not rebuild the others. Within a Dockerfile the granularity is the target's stage closure — everything reachable from it through FROM and --from= — so editing one stage rebuilds that stage and its descendants, not every image the Dockerfile serves.

Within a run no image is built more than once: a push to main skips the build job (the pull request already proved the build) and goes straight to publish, which pushes to both registries from a single docker buildx build.

An add-on is built on top of the image its parent stage published, pinned by digest (--build-context <parent>=docker-image://…@sha256:…). FROM full names a stage rather than the published base image, so without that the add-on would re-run the base's apt-get upgrade and could end up on a different package set than the base image it extends. The recipe hash still covers the parent's instructions, so a change to the base rebuilds every add-on.

A release of an image whose recipe is already published is not rebuilt either: its immutable tag is added to the digest that the moving tag already points at (docker buildx imagetools create --prefer-index=false, a digest-preserving carbon copy). The release is then exactly the image CI has been using, and one cosign signature still covers both tags.

The hash cannot see upstream changes (a new ubuntu:24.04 base image, updated distro packages), so two triggers ignore it and rebuild unconditionally: the weekly schedule, and a workflow_dispatch with its force checkbox left on.

A registry that answers "no such tag" means the image has to be built. A registry we cannot reach at all (after three attempts) fails the job instead: an image we cannot see is not an image we may assume is up to date, and rebuilding it blindly would paper over a broken registry.

A second workflow, cleanup.yml, deletes stale versions of the GHCR package: untagged digests left behind by re-pushed moving tags and orphaned cosign sha256-* signature tags whose image is gone. It keeps all tagged images, anything still referenced by them, and signatures of existing images. It runs automatically after every successful GHCR publish and can also be triggered manually, where it defaults to a dry run — inspect the log, then re-run it with dry-run unchecked. Note that superseded digests are pruned right after each publish, so pulling a moving tag's previous image by digest is not supported.

Releasing a new image version

See RELEASING.md for the step-by-step process.

License

The original Dockerfile was taken from OpenModelica/OpenModelicaBuildScripts. See LICENSE.md.

About

OpenModelica build-deps Docker Image

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages