Several ways to build a container image
Using Docker to build container images in your CI pipelines ? Alternative solutions exist, let’s explore some of them.
Quick overview
The following illustrates the usage of each of these tools in GitLab CI, it also details the usage of Docker as a reference.
build image with Docker:
stage: build
variables:
TAG: docker
image: docker:27.3-cli
services:
- docker:27.3-dind
before_script:
- docker login -u "gitlab-ci-token" -p $CI_JOB_TOKEN $CI_REGISTRY
script:
- docker buildx create --use
- docker buildx build -t $CI_REGISTRY_IMAGE:$TAG . --push
details
- before_script is used to log in to the GitLab registry
- script defines 2 commands:
- creation of a builder
- usage of this builder to create and to push the image
build image with Kaniko:
stage: build
variables:
TAG: kaniko
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
before_script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"gitlab-ci-token\",\"password\":\"$CI_JOB_TOKEN\"}}}" > /kaniko/.docker/config.json
script:
- /kaniko/executor --context . --dockerfile ./Dockerfile --destination $CI_REGISTRY_IMAGE:$TAG
details
- before_script creates a /kaniko/.docker folder and a config.json file inside it. This file contains the credentials to authenticate against the GitLab registry
- script runs Kaniko executor which creates and pushes the image to the GitLab registry
build image with Buildah:
stage: build
variables:
TAG: buildah
image: ubuntu:24.04
before_script:
- apt-get -y update && apt-get -y install buildah runc
- buildah login --tls-verify=false -u "gitlab-ci-token" -p "$CI_JOB_TOKEN" $CI_REGISTRY
script:
- buildah bud --tls-verify=false -t $CI_REGISTRY_IMAGE:$TAG .
- buildah push --disable-compression --tls-verify=false $CI_REGISTRY_IMAGE:$TAG
details
- before_script installs buildah and runc component, then it logs in to the GitLab registry
- scripts builds the image and pushes it to the registry
build image with Podman:
stage: build
variables:
TAG: podman
image: quay.io/podman/stable
before_script:
- podman login -u "gitlab-ci-token" -p $CI_JOB_TOKEN $CI_REGISTRY
script:
- podman build -t $CI_REGISTRY_IMAGE:$TAG .
- podman push $CI_REGISTRY_IMAGE:$TAG
details
- before_script logs in to the GitLab registry
- script builds and pushes the image
Example
The example above is based on a sample application in GitLab. Each code change pushed to the repository triggers the CI which builds 4 images:
- registry.gitlab.com/lucj/shapes:docker
- registry.gitlab.com/lucj/shapes:kaniko
- registry.gitlab.com/lucj/shapes:buildah
- registry.gitlab.com/lucj/shapes:podman
Next it pushes the images to the GitLab registry:
These images can be run using Docker, Podman or any other OCI compatible container runtime.
⚠️
Because these images were built for amd64, they will not work on arm64 (Apple Silicon)