Skip to content
CommonLayer

Container image standard

Version 1. Every CommonLayer image is built to these rules.

Rules

Image standard rules
IdentifierRule
baseThe final stage starts from the CommonLayer base image, pinned by digest.
sourceUpstream software is built from the upstream release tarball, verified by SHA-256 (and by signature where upstream signs) in the build stage. Version and checksum are build arguments that mirror commonlayer.yaml.
multi-stageBuild tools exist only in build stages. The final image contains no compiler, no package manager, no curl or wget, and no debugging tools.
non-rootRuns as UID/GID 10001:10001 (commonlayer). No USER root, no setuid binaries, no sudo or gosu.
filesystemApplication files in /app (read-only), configuration in /etc/commonlayer/<app>, data in /var/lib/commonlayer/<app>, logs in /var/log/commonlayer/<app> (applications log to stdout/stderr by default), scratch in /tmp.
read-only-rootfsWorks with a read-only root filesystem when the documented writable paths are mounted.
entrypoint/usr/local/bin/commonlayer-entrypoint: POSIX sh, set -eu, ends in exec. Supports <VAR>_FILE for every secret variable and never prints secrets.
signalsThe application is PID 1 after exec and shuts down gracefully on SIGTERM; STOPSIGNAL is set where upstream differs.
healthcheckA HEALTHCHECK using cl-probe or the application's own client.
envVariables are prefixed with the application name. Where upstream's official image has an established variable (for example POSTGRES_PASSWORD), the same name is supported to ease migration.
labelsOCI annotations org.opencontainers.image.{title, description, version, revision, created, source, url, documentation, licenses, vendor, base.name, base.digest} and org.commonlayer.{project, variant, upstream.version, revision, standard}.
platformslinux/amd64 and linux/arm64, built on native runners and joined into one index.
reproducibilitySOURCE_DATE_EPOCH is honoured and inputs are pinned. Documented as best effort, not claimed as bit-for-bit.
licensesUpstream license texts under /usr/share/licenses/; a third-party license inventory generated from the SBOM is published with each release.
sbom-sign-provenanceSPDX and CycloneDX SBOMs, a cosign keyless signature and a SLSA v1 provenance attestation, all attached to the digest.

Scope

The standard applies to every container image published by a CommonLayer project. It is checked in three places: the project's own tests (run locally and in CI), the scan gate in its release workflow, and the platform's verification policy, which checks among other things that the image user is not root, that the required labels are present, that every required platform is in the index, and that a signature, SBOM and provenance attestation from the registered identity exist for the digest.

A project's repository is also checked statically, without running anything: by the onboarding scan when it is connected through the CommonLayer GitHub App, and afterwards by the repository guardrails. Their image rules (image.non_root, image.base, image.healthcheck and others) refer to the identifiers below, and each finding names the Dockerfile line. See the project template and the scan.

The base image

The CommonLayer base image is built in two stages. An Alpine stage, pinned by digest, installs a minimal package set into an empty root and then removes the package manager; the final stage is FROM scratch plus that root. It contains musl, BusyBox with a reduced set of applets (the shell and core utilities entrypoints need; network clients such as wget, nc, telnet and ftp removed), CA certificates, time zone data, the commonlayer user and group with ID 10001, the standard directories with correct ownership, and cl-probe.

The package database is kept on purpose, so that scanners can identify every package. cl-probe is a small static program for health checks (http, tcp and file modes), which removes the need for curl or wget in images. The base image is itself a CommonLayer project with its own manifest, SBOM, signature, scans and a weekly rebuild.

Filesystem layout

/app
Application files, read-only.
/etc/commonlayer/<app>
Configuration.
/var/lib/commonlayer/<app>
Persistent data; mount a volume here.
/var/log/commonlayer/<app>
Log files, when an application cannot log to stdout/stderr.
/tmp
Scratch space; mount an emptyDir or tmpfs when the root filesystem is read-only.

Images run as UID 10001. When migrating from images that use another UID (Bitnami images use 1001, for example), existing volumes need their ownership adjusted; the migration guides explain how for each project.

Deviations

Some software cannot meet a rule as written. A project documents each deviation in its commonlayer.yaml as { standard: <identifier>, reason: <text> }; the identifier must be one of those above. Deviations are part of the project's public manifest. An undocumented deviation — for example an image whose user is root — fails verification and is not published.

What is not claimed

  • No SLSA level is claimed beyond what the build actually satisfies. Provenance states what was built, from which commit, by which workflow.
  • “No known vulnerabilities” describes the last scan, not the absence of vulnerabilities.
  • Reproducibility is best effort, not a bit-for-bit guarantee.
  • No CIS or FIPS conformance is claimed.
  • Applying Apache-2.0 to a Dockerfile does not relicense the image's contents; each image keeps its upstream licenses and publishes an inventory.

Charts follow a companion Helm chart standard.