Container component
Container images built from branches receive an immutable release tag composed of the normalized branch name and full commit SHA. Protected branches and the default branch also receive a mutable normalized branch tag. For example, a protected dev pipeline publishes dev and dev.<commit-sha>. The component sanitizes unsupported characters and truncates only the branch portion when necessary, keeping the complete tag within the OCI 128-character limit. Unprotected non-default branches and merge request pipelines publish only the commit-based tag, preventing them from overwriting shared mutable tags.
Every built image also receives standard OCI image labels from GitLab's predefined CI/CD variables. When the corresponding GitLab value is available, the component records the build time, commit author, project URL and source, release version, commit revision, root namespace as vendor, project title, and project description. This metadata makes the image traceable without requiring labels in each project's Containerfile.
When GITHUB_TOKEN is available, the container and buildah components automatically authenticate their OCI client to ghcr.io before building or publishing. The token owner is discovered through the GitHub API. Set GITHUB_USER when API-based discovery is unavailable or when the registry login must use a specific GitHub username. The token needs the GitHub Packages scopes required by the images being pulled or pushed. Automatic login is best-effort so an unrelated registry operation can continue; a later GHCR pull or push still fails with its native error when credentials are required.
When the container context contains a README.md, its content replaces the project description in the standard org.opencontainers.image.description OCI label. Registry interfaces and image inspection tools can use this label as the container summary. Without a context README.md, the GitLab project description remains the image description.
Stable SemVer tag pipelines publish latest only when their tag is the newest stable release. Retrying an older release pipeline still publishes its immutable version tag without moving latest backwards.
Usage
- Create a new project
- Create a
Containerfile.
FROM alpine
- Create GitLab pipeline file
.gitlab-ci.yml:
include:
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/common@stable
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/container@stable
inputs:
name: myapplication
path: .
Pass build arguments to the container builder
Use the args input when your Containerfile needs build-time values. The value is passed through to the selected builder, so use the same syntax you would pass to podman build or buildah build.
include:
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/common@stable
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/container@stable
inputs:
name: myapplication
path: .
args: "APP_ENV CI_COMMIT_SHA"
variables:
APP_ENV: production
Example Containerfile consuming the build arguments:
FROM registry.access.redhat.com/ubi10/ubi-minimal:10.1
ARG APP_ENV=development
LABEL org.opencontainers.image.version=$CI_COMMIT_SHA
RUN echo "Building for ${APP_ENV}"
Publish to your own registry
The component can publish to any OCI-compatible registry, including a self-managed Harbor instance and Azure Container Registry. Configure the registry through component inputs and keep its credentials in GitLab CI/CD variables.
Create these variables at the narrowest level that should share the registry:
| GitLab level | Where to configure it | Use it when |
|---|---|---|
| Instance | Admin > Settings > CI/CD > Variables | Every group and project on a self-managed GitLab instance uses the same registry. |
| Group | Group > Settings > CI/CD > Variables | Projects below one group share a registry namespace or robot account. |
| Project | Project > Settings > CI/CD > Variables | One project needs its own registry namespace or credentials. |
Define the following variables. Mark the password masked, and mark credentials protected when only protected branches and tags may publish. Use CI_REGISTRY_AUTH_FILE when the job also needs credentials for additional registries; the common component merges them into the same job-scoped configuration.
| Variable | Example | Description |
|---|---|---|
CI_REGISTRY | harbor.example.com | Registry hostname without https://. |
CI_REGISTRY_PROJECT_PATH | platform/my-project | Repository path below the registry hostname. The component appends its name. |
CI_REGISTRY_USER | robot$ci-tools | Robot account, service principal, or registry user. |
CI_REGISTRY_PASSWORD | masked variable | Robot secret, client secret, or registry password. |
CI_REGISTRY_AUTH_FILE | protected file variable | Optional Docker-compatible JSON containing credentials for other registries used inside the job. |
Publish to the registry via components:
include:
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/common@stable
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/container@stable
inputs:
name: myapplication
path: .
This publishes myapplication below $CI_REGISTRY/$CI_REGISTRY_PROJECT_PATH. Overriding the standard registry variables keeps the same component configuration portable between GitLab.com, self-managed GitLab, and external registries.
Harbor
Create a project or system robot account with pull and push repository permissions. Use the Harbor hostname as CI_REGISTRY, the Harbor project and repository prefix as CI_REGISTRY_PROJECT_PATH, the robot name as CI_REGISTRY_USER, and its generated secret as CI_REGISTRY_PASSWORD. Harbor does not show the secret again, so store it in GitLab when the account is created. See Harbor robot accounts.
Azure Container Registry
Use the registry login server, such as myregistry.azurecr.io, as CI_REGISTRY. For unattended pipelines, create a Microsoft Entra service principal with repository push and pull permissions. Use its application ID as CI_REGISTRY_USER and its client secret as CI_REGISTRY_PASSWORD. Azure registries using RBAC Registry Permissions commonly use the AcrPush role; registries using repository-scoped ABAC require the corresponding repository permissions. See Azure Container Registry service-principal authentication.
Test the configuration
Run the pipeline from a branch that can read the configured credentials. The build log should report the selected registry and successful login without printing the password. The component test pipeline also publishes an expiring image to ttl.sh with test-only credentials, covering the authenticated OCI client path without retaining a permanent image.
Inputs
| Name | Description | Default | Type |
| --- | --- | --- | --- |
| args | Arguments to pass to the builder. | string | |
| cache-enabled | Should registry-backed build cache be used? | false | boolean |
| containerfile-path | Alternate path to the Containerfile, if either Dockerfile or Containerfile in the conect directory. | string | |
| dependencies | The dependencies that this job depends on. | [] | array |
| name | Name for the pipeline jobs and the container. | $CI_PROJECT_NAME | string |
| needs | The jobs that this job depends on. | [] | array |
| path | Path to the directory containing Container sources / context. | . | string |
| registry | Registry to store container image releases in | $CI_REGISTRY | string |
| repository-path | Repository to store container image releases in | $CI_REGISTRY_PROJECT_PATH | string |
| rules | The jobs that this job depends on. | [{"if":"$CI_PIPELINE_SOURCE == \"schedule\"","when":"never"},{"if":"$CI_PIPELINE_SOURCE == \"merge_request_event\"","when":"on_success"},{"when":"on_success"}] | array |
| runtime | Repository to store container image releases in | podman | string |
| scanners | Scanners to use. none, vuln, license, secret, misconfig | ["vuln","secret","license","misconfig"] | array |
| scanning-allow-failure | Should the pipeline fail if scanning the built container image fails? | false | boolean |
| scanning-enabled | Should the built container image be scanned? | true | boolean |
| scanning-ignore-unfixed | Exclude vulnerabilities that do not have a fix available. | true | boolean |
| scanning-severity | What level of severity should cause scanning of the built container to fail? | CRITICAL | string |
| scanning-timeout | How long should the scanning process be allowed to run before timing out? Use format e.g. 5m0s | 30m0s | string |
| secrets | Secrets to pass to the builder. | string | |
| signing-enabled | Should the built container image be signed? | true | boolean |
| stage | The pipeline stage that the jobs belongs to. | build | string |
| tags | The runners that this job depends on. | [] | array |
| version | Internal version of the nested component to use. | main | string |