container#
Overview#
Build, lint, and publish OCI container images in CI.
Building#
Two build strategies are defined:
- Docker-in-Docker (planned): Build on a runner with the Docker socket mounted.
- Kaniko: Build using Google's Kaniko tool.
For the most common use cases, the Kaniko pipeline is recommended, as it has minimal requirements for use.
Linting#
A hadolint job is defined for Dockerfile validation.
Versioning#
Two tags are produced for every pipeline that runs:
${CONTAINER_VERSION}
${CONTAINER_VERSION}-${CI_COMMIT_SHORT_SHA}
In addition, the default branch also publishes the latest
tag.
It is recommended to garbage collect old tags.
Usage#
Project setup#
A Dockerfile in the project root is the minimum requirement to use this pipeline.
Variables#
The pipelines defined in this project consume some or all of the variables defined on this page.
CONTAINER_BUILD_OPTS
-
Extra options to pass to the container build command.
See Pass container build options for more details.
CONTAINER_COMMIT_SHA
-
Commit SHA for the container pipeline. Defaults to
${CI_COMMIT_SHA}
.variables: CONTAINER_COMMIT_SHA: "
CONTAINER_COMMIT_SHORT_SHA
-
Commit short SHA for the container pipeline. Defaults to
${CI_COMMIT_SHORT_SHA}
. CONTAINER_CONTEXT
-
Container build context. Defaults to
${CI_PROJECT_DIR}
.Example:
variables: CONTAINER_CONTEXT: "${CI_PROJECT_DIR}/some/project/subpath"
CONTAINER_DOCKER_ARCH
-
docker-multiarch
onlyThis is the name of the machine architecture as defined by Docker.
Common architectures:
amd64
: x86 64-biti386
: x86 64-bitarm64v8
: ARMv8 64-bitarm32v6
: ARMv6 32-bitarm32v7
: ARMv7 32-bit
For all possible architecture values, see this page.
CONTAINER_DOCKER_PLATFORM
-
docker-multiarch
onlyThis is the value that the
docker
CLI expects when using the--platform
flag.Common platforms:
linux/amd64
: Linux, x86 64-bitlinux/386
: Linux, x86 32-bitlinux/arm64
: Linux, ARMv8 64-bitlinux/arm/v6
: Linux, ARMv6 32-bitlinux/arm/v7
: Linux, ARMv7 32-bit
This list can be generated by running
docker buildx ls
. CONTAINER_DOCKERFILE
-
Container build Dockerfile. Defaults to
${CI_PROJECT_DIR}/Dockerfile
.Example:
variables: CONTAINER_DOCKERFILE: "${CI_PROJECT_DIR}/deploy/docker/Dockerfile"
A fully qualified path to the Dockerfile is required.
CONTAINER_IMAGE
-
Full name of container image tag. Defaults to
${CONTAINER_NAME}:${CONTAINER_VERSION}
.Example:
variables: CONTAINER_IMAGE: "${CONTAINER_NAME}:${CONTAINER_VERSION}"
CONTAINER_MULTIARCH_PLATFORMS
-
docker-multiarch
onlyConfigures the docker-multiarch pipeline to build for multiple architectures.
Defaults to
amd64 arm32v6 arm32v7 arm64v8 i386
, which enables all currently supported architectures.variables: # only build for arm CONTAINER_MULTIARCH_PLATFORMS: arm32v6 arm32v7 arm64v8
For a list of supported values, see
CONTAINER_DOCKER_ARCH
. CONTAINER_NAME
-
Defaults to
${CONTAINER_REGISTRY}${CONTAINER_NAME_SUFFIX}
.variables: CONTAINER_NAME: "docker.io/jdoe/mycontainer"
CONTAINER_NAME_SUFFIX
-
Defaults to an empty string.
variables: CONTAINER_NAME_SUFFIX: "/variant"
CONTAINER_PROXY
-
Defaults to
${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/
.variables: # proxy images through harbor.example.com CONTAINER_PROXY: "harbor.example.com/docker/library/"
Note
Only GitLab Dependency Proxy is currently supported.
For more info, see Configure a Docker Hub proxy.
CONTAINER_REGISTRY
-
Container registry to publish images to. Defaults to
${CI_REGISTRY_IMAGE}
.Example:
variables: # push to another project's registry CONTAINER_REGISTRY: "registry.gitlab.com/brettops/example/project"
CONTAINER_REGISTRY_USER
-
Defaults to
${CI_REGISTRY_USER}
. CONTAINER_REGISTRY_PASSWORD
-
Defaults to
${CI_REGISTRY_PASSWORD}
. CONTAINER_VERSION
-
Defaults to
${CI_COMMIT_REF_NAME}${CONTAINER_VERSION_SUFFIX}
.variables: # pull the version from another variable CONTAINER_VERSION: "${ANOTHER_VERSION_VARIABLE}"
CONTAINER_VERSION_SUFFIX
-
Defaults to an empty string.
variables: # append '-ubuntu' to the image tag CONTAINER_VERSION_SUFFIX: "-ubuntu"
Default pipelines#
docker
pipeline#
This pipeline is a minimal container build with Docker + BuildKit. It's useful for when you need the extra features of BuildKit, but has a slower startup time.
Usage#
Include the pipeline in the .gitlab-ci.yml
file:
include:
- project: brettops/pipelines/container
file: docker.yml
docker-multiarch
pipeline#
This pipeline builds full multi-arch Docker containers. It builds them in separate jobs for parallelism and then recombines them in a later manifest creation job.
Usage#
Include the pipeline in the .gitlab-ci.yml
file:
include:
- project: brettops/pipelines/container
file: docker-multiarch.yml
Optionally, define architectures to build in a space-separated list. Defaults to all available:
variables:
CONTAINER_MULTIARCH_PLATFORMS: amd64 arm32v6 arm32v7 arm64v8 i386
For a list of supported values, see
CONTAINER_DOCKER_ARCH
.
kaniko
pipeline#
This pipeline builds containers via Kaniko. Kaniko lacks many features of Docker, but it's highly portable across runner executors as it can run without root access.
Usage#
Include the pipeline in the .gitlab-ci.yml
file:
include:
- project: brettops/pipelines/container
file: kaniko.yml
Custom pipeline#
The following snippet shows how a custom pipeline might be defined:
stages:
- test
- build
- deploy
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_OPEN_MERGE_REQUESTS
when: never
- when: always
include:
- project: brettops/pipelines/container
file: .include.yml
container-hadolint:
extends: .container-hadolint
container-docker:
extends: .container-docker
container-kaniko:
extends: .container-kaniko
Use cases#
Image tag names#
${CONTAINER_REGISTRY}${CONTAINER_NAME_SUFFIX}:
The following variables are available to customize the generated image tag names:
Pass build options#
This section is a stub. Please help by expanding it.
The CONTAINER_BUILD_OPTS
variable may be used to pass
extra arguments to the container build command.
Docker and Kaniko sometimes have different names for the same option.
- For Docker jobs, see https://docs.docker.com/engine/reference/commandline/buildx_build/.
- For Kaniko jobs, see https://github.com/GoogleContainerTools/kaniko#additional-flags.
--build-arg
#
--build-arg
is the same for Docker and Kaniko.
container-kaniko:
variables:
CONTAINER_BUILD_OPTS: >-
--destination ${CONTAINER_NAME}:3.4.4-${CONTAINER_VERSION}
--destination ${CONTAINER_NAME}:3.4-${CONTAINER_VERSION}
--destination ${CONTAINER_NAME}:3-${CONTAINER_VERSION}
container-kaniko:
variables:
CONTAINER_BUILD_OPTS: >-
--build-arg PIP_INDEX_URL=$PYTHON_PYPI_DOWNLOAD_URL
--platform linux/arm/v6
--tag
(docker) / --destination
(kaniko)#
TBD.
Cross-platform container build support#
This section is a stub. Please help by expanding it.
Use a custom build context#
This section is a stub. Please help by expanding it.
Use a custom Dockerfile#
This section is a stub. Please help by expanding it.
Use a custom registry#
This section is a stub. Please help by expanding it.
Use a Docker Hub proxy#
Docker Hub rate limits container image pulls. These limits are easily hit in a CI environment, so it's recommended to enable a container proxy.
GitLab's Dependency
Proxy feature
allows you to proxy Docker Hub containers through GitLab. However, rather than
use these values directly, use the CONTAINER_PROXY
variable to make it easy to change proxy location in the future without updating
every repository.
When this pipeline is included, CONTAINER_PROXY
is set by default to the
following value:
variables:
CONTAINER_PROXY: "${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/"
Note the trailing /
! This allows projects to continue to function if
CONTAINER_PROXY
is not configured.
It's recommended to configure CONTAINER_PROXY
at the group level, so that CI
jobs can use proxied containers. Here is an example that uses the
image keyword.
image: "${CONTAINER_PROXY}alpine:latest"
This pipeline will automatically add CONTAINER_PROXY
as a --build-arg
, so
you can proxy FROM
images in Dockerfiles as well:
ARG CONTAINER_PROXY
FROM ${CONTAINER_PROXY}node:lts-bullseye
Use a private PyPI repository#
This section is a stub. Please help by expanding it.