Container Images¶
Images in use¶
Every reference in .github/workflows/ci.yml, .devcontainer/docker-compose.yml
and ci/docker-compose.bdd.yml is pinned by digest — <repo>@sha256:…. The tag
below is the readable handle; the digest in the files is what actually resolves.
The tag is kept alongside each reference: as a trailing comment on a container:
or Compose image: key, and in the comment above the step for a docker run
invocation, whose line continuation cannot carry one. Digests are deliberately
not repeated here, so there is one authoritative copy per reference and nothing
to drift.
| Image | Tag | Used by |
|---|---|---|
ghcr.io/cososo-ltd/cpputest |
sha-6715942 |
devcontainer (gcc service), most CI jobs. Now ships include-what-you-use 0.23 (clang_19) matching the cpputest-clang build, so local iwyu runs work in the gcc container |
ghcr.io/cososo-ltd/cpputest-clang |
sha-5905aea |
clang compose service, build-linux-clang CI job, analyze-iwyu CI job |
ghcr.io/cososo-ltd/cpputest-freertos |
sha-ad10bf2 |
freertos-host compose service, build-freertos-host-tdd-plustcp CI job — adds FreeRTOS-Kernel / Plus-TCP / Plus-FAT / lwIP / FatFs / Mbed TLS sources for host-TDD of FreeRTOS adapters against fakes; inherits IWYU from the rebased cpputest base, enabling the freertos-aware analyze-iwyu lane |
ghcr.io/cososo-ltd/cpputest-freertos-cross |
sha-ad10bf2 |
freertos-target compose service, build-freertos-target-plustcp CI job, behave-freertos BDD service, bdd-freertos-qemu-plustcp CI job — adds gcc-arm-none-eabi, libnewlib-arm-none-eabi, gdb-multiarch (aliased as arm-none-eabi-gdb), qemu-system-arm, python3 + behave, FreeRTOS-Kernel / Plus-TCP / Plus-FAT / lwIP / FatFs sources at /opt/freertos-kernel / /opt/freertos-plus-tcp / /opt/freertos/plus-fat / /opt/lwip / /opt/fatfs for cross builds, on-QEMU runs, and BDD scenarios driving a QEMU target |
balabit/syslog-ng |
4.8.2 |
syslog-ng-linux and syslog-ng-freertos services — BDD test oracles, one per target pair. Pinned to the 4.8 LTS line; 4.11.0 (latest as of 2026-02-24) regressed by aborting on STATS over the control socket, which crashed the oracle and cascaded to the dev-container network when freertos-target shares the namespace. |
ghcr.io/cososo-ltd/behave |
sha-be8da62 |
behave-linux service — Debian trixie + Python 3.12 + Behave for Linux BDD scenarios. The FreeRTOS BDD runner uses the cpputest-freertos-cross image instead (which carries QEMU + Behave). |
ghcr.io/cososo-ltd/mkdocs-mkdoxy |
sha-34173c0 |
docs-build CI job — builds the MkDocs documentation site. Doxygen 1.9.4 + mkdocs 1.6.1 + mkdocs-material 9.7.6 + mkdoxy 1.2.8 + mkdocs-github-admonitions-plugin 0.1.1. mkdoxy renders Core/Interface/*.h as native Material API pages. |
Docker Compose setup¶
The devcontainer uses Docker Compose (.devcontainer/docker-compose.yml).
VS Code connects to the gcc service (GCC). The clang service is on-demand only:
it starts when you explicitly run a command against it and stops when done.
BDD testing pairs each target with its own syslog-ng oracle so jobs running
in parallel (or developers switching containers) never interfere:
| Target | Behave runner | Oracle |
|---|---|---|
| Linux | behave-linux |
syslog-ng-linux |
| FreeRTOS | inside freertos-target (image carries both QEMU and Behave) |
syslog-ng-freertos |
The gcc service depends on syslog-ng-linux so it starts automatically with the
devcontainer; the freertos-target service depends on syslog-ng-freertos and shares
its network namespace via network_mode: service:syslog-ng-freertos, so QEMU's
slirp gateway 10.0.2.2 NATs to the pair's loopback where syslog-ng-freertos is
listening on 0.0.0.0:5514. Both oracles also alias as the bare hostname syslog-ng
on their network so the existing BDD target wiring (Bdd/Targets/Linux/BddTarget*Config.c,
the BDD step helpers) keeps resolving without per-target host overrides. The
pairs never run together, so the alias collision is academic.
As more cross-compilation targets are added, each gets its own oracle pair in the
same shape (syslog-ng-<target> + a runner service or in-container Behave).
FreeRTOS networking backend selection¶
cpputest-freertos and cpputest-freertos-cross both ship the
FreeRTOS-Plus-TCP and lwIP source trees side-by-side, and a default build
selects both — you can work on either networking stack, and run both
stacks' unit tests, without reconfiguring. The configure says so:
-- SolidSyslog tests: both FreeRTOS networking stacks selected — lwIP and Plus-TCP suites build together.
To work in one stack only, deselect the other with its own switch
(-DSOLIDSYSLOG_PLUSTCP=OFF or -DSOLIDSYSLOG_LWIPRAW=OFF), which drops that
platform and its tests together. The lwIP lint lanes do exactly this.
Which BDD ELF a cross build produces is separate, and maintainer-only —
SOLIDSYSLOG_BDD_FREERTOS_NET=PLUSTCP (default) or LWIP. It selects a test
artefact, not a platform — platforms are named in SOLIDSYSLOG_PLATFORMS like
everything else.
CI runs both cross targets in isolation, and both are required checks:
build-freertos-target-plustcp and build-freertos-target-lwip.
Running the clang build locally¶
From a host terminal (not inside the devcontainer):
docker compose -f .devcontainer/docker-compose.yml run --rm clang \
cmake --preset clang-debug
docker compose -f .devcontainer/docker-compose.yml run --rm clang \
cmake --build --preset clang-debug --target junit
Updating an image¶
When a new image tag is available:
- Build and push the new image in the container image repo
- Resolve the new tag to its digest:
docker buildx imagetools inspect ghcr.io/cososo-ltd/<image>:sha-<new> \
--format '{{.Manifest.Digest}}'
Pin exactly what this command prints — the image index digest for a
multi-architecture image, or the single manifest digest for a
single-platform one. Do not substitute a per-platform digest dug out of
--raw: for an index that would nail the reference to one architecture.
Of the images here, only balabit/syslog-ng is genuinely multi-arch
(linux/amd64 and linux/arm64); the rest are linux/amd64 only.
- Update the digest and the accompanying tag comment in every file that
references the image (see table below), plus the tag in
docs/containers.md - Rebuild the devcontainer (
Ctrl+Shift+P→ "Dev Containers: Rebuild Container") and verify locally - Raise a PR: use
chore: bump container image to <sha>as the title
| Image | Files to update |
|---|---|
cpputest |
.devcontainer/docker-compose.yml, .github/workflows/ci.yml, docs/containers.md |
cpputest-clang |
.devcontainer/docker-compose.yml, .github/workflows/ci.yml, docs/containers.md |
cpputest-freertos |
.devcontainer/docker-compose.yml, .github/workflows/ci.yml, docs/containers.md |
cpputest-freertos-cross |
.devcontainer/docker-compose.yml, .github/workflows/ci.yml, ci/docker-compose.bdd.yml, docs/containers.md |
behave |
.devcontainer/docker-compose.yml, ci/docker-compose.bdd.yml, docs/bdd.md, docs/containers.md |
mkdocs-mkdoxy |
.github/workflows/ci.yml, docs/containers.md |
syslog-ng |
.devcontainer/docker-compose.yml, ci/docker-compose.bdd.yml, docs/containers.md |
syslog-ng is the one upstream image in that table — it is published by
balabit, not by us, so step 1 does
not apply and the version is chosen rather than built. Read the 4.8 LTS pinning
rationale in the first table before moving it.
The cpputest-freertos and cpputest-freertos-cross images both come from
CppUTestFreertosDocker.
A single push to that repo's main rebuilds and publishes both images at
the same sha-<short> tag; always update both rows together.
The mkdocs-mkdoxy image comes from
MkdocsMkdoxyDocker; a push to
that repo's main rebuilds and publishes it at a new sha-<short> tag.
mkdocs-mkdoxy is a CI-only image; it is not a devcontainer service, so the
generic "rebuild the devcontainer and verify" step above does not exercise it.
Verify a tag bump by running the same command the docs-build job runs, from the
repo root, before raising the bump PR:
docker run --rm -v "$PWD:/docs" \
ghcr.io/cososo-ltd/mkdocs-mkdoxy@sha256:<new> mkdocs build --strict
All references to a given image must use the same digest. Never update one without the others. To check that invariant across the tree:
grep -rhno 'ghcr.io/cososo-ltd/[a-z-]*@sha256:[0-9a-f]*\|balabit/syslog-ng@sha256:[0-9a-f]*' \
.github/workflows/ci.yml .devcontainer/docker-compose.yml ci/docker-compose.bdd.yml \
| sed 's/^[0-9]*://' | sort -u
One line per image means every reference agrees; two lines for the same image name means a bump was applied unevenly.
Switching to a different container as the devcontainer¶
The available services and the build preset each one drives:
| Service | Use case | BUILD_PRESET |
|---|---|---|
gcc |
Primary C/C++ development (default) | debug |
clang |
Clang-specific debugging / portability | clang-debug |
freertos-host |
TDD of FreeRTOS adapters against host-side fakes | debug |
freertos-target |
Cross builds, on-QEMU runs, GDB attach (Cortex-M3, mps2-an385), BDD against the QEMU target | freertos-cross |
behave-linux |
Linux BDD scenario development (Python + Behave) | (none — cmake skipped) |
To switch:
- In
.devcontainer/devcontainer.json, change"service": "gcc"to the target service name (e.g."freertos-target"). Ctrl+Shift+P→ "Dev Containers: Rebuild Container".- Work normally;
Ctrl+Shift+Band all other tasks pick up the right preset via$BUILD_PRESET.
When done, revert "service" back to "gcc" and rebuild again.
The same VS Code keys work across every service:
Ctrl+Shift+Bruns thebuild and testtask, which adapts to the activeBUILD_PRESET. Underfreertos-crossit builds theSolidSyslogBddTargetELF; underdebug/clang-debugit builds and runsSolidSyslogTests; withBUILD_PRESETempty (thebehave-linuxservice) it runsbehave.F5debugs:Debug SolidSyslogTests (host): works ingcc,clang, andfreertos-host(path resolves via${env:BUILD_PRESET}). Builds first via the samebuild and testtask and stops atmain.Debug FreeRTOS BDD Target (QEMU): works infreertos-target(cortex-debug + arm-none-eabi-gdb + qemu-system-arm). Stops atmainviarunToEntryPoint.- After switching the devcontainer service, pick the matching config from the Run-and-Debug dropdown once. VS Code remembers the last-picked config per workspace (not per container), so the previous choice survives a container rebuild; a stale selection will fail with the wrong debugger type.
Ctrl+Shift+P→ "Tasks: Run Task" →run on QEMU (FreeRTOS): one-shot QEMU run for sanity-checking the build, output to the integrated terminal. Use only in thefreertos-targetservice.
For the FreeRTOS BDD target, see Bdd/Targets/FreeRtos/README.md for build / run / GDB-attach instructions.