Buildkit
The preferred method for building container images is Buildkit since it provides the most caching resulting in the best performance.
When setting up a container build from scratch the follow is preferred.
container:
stage: build
variables:
CEDARCI_INCREMENTAL: "true"
CEDARCI_SERVICE_BUILDKIT: "true"
script:
- |
docker buildx build \
--builder fast \
--cache-from "type=local,src=.cache" \
--cache-to "type=local,mode=max,dest=.cache" \
.
Ensure the .dockerignore
file excludes the .cache
directory.
The combination of the local .cache
and CEDARCI_INCREMENTAL
from the Intelligent Cache provides the best performance.
Docker
Existing Docker-in-Docker builds will have a tuned Buildkit configuration injected. The following
.gitlab-ci.yml
file demonstrates a container build using the common DinD technique that would be upgraded.
container:
stage: build
variables:
DOCKER_VERSION: 28.1.1
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
services:
- name: docker:${DOCKER_VERSION}-dind
alias: docker
command: ["--tls=false"]
image: docker:${DOCKER_VERSION}
script: docker buildx build .
To achieve maximum caching the --cache-{from,to}
flags will need to be added as shown in the Buildkit
section.
If problems are encountered with the injected configuration it may be disabled by setting
CEDARCI_SERVICE_AUTO_DETECT_DISABLE
to true
.
Builds using the DOCKER_BUILDKIT=1 docker build .
style cannot benefit from the tuned configuration and should be
adjusted to docker buildx build .
.
Gitlab Auto DevOps
Container builds performed by Gitlab Auto DevOps will automatically be configured to utilize local caching. The existing registry based caching will remain which may reduce performance when compared to only a warm local cache, but is still better than without.
Local caching will be disabled by any of the following:
CEDARCI_AUTO_DEVOPS_CACHE_DISABLE
is set totrue
AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS
is configured since it may conflict
Workflow
Instead of the common approach of building everything in a Dockerfile
it is generally preferred to build the
application outside the container build process and copy the result into the container. Builds on the outside will
benefit from the Intelligent Cache and thus be more performant and reliable.
For those already avoiding the build layers ending up in the final image using a multistage build this approach simply moves the first build into the CI job and copies the result.
For example, a multistage build like the following:
FROM toolchain:1.2.3 as build
RUN install_dependencies
RUN compile
FROM scratch
COPY --from=build /app /app
Becomes:
container:
image: toolchain:1.2.3
script:
- install_dependencies
- compile
- docker buildx build .
FROM scratch
COPY app /app
Ignore
The scope of files considered during the build process can be control via a .dockerignore
file. The less files
considered the better the performance.
While irrelevant directories and files can be excluded, it is often easier to maintain an allow list.
*
!vendor/
!src/
!dep.list
!dep.lock
Memory
All services default to 2Gi
of memory unless configured via service_memory
. An increase can
be applied directly to a service or the whole job using a variable.
container:
variables:
KUBERNETES_SERVICE_MEMORY_REQUEST: "4Gi"
Storage
By default, the Buildkit and Docker services are configured with 15
gigabytes of storage. The value may adjusted using the
following variables.
CEDARCI_SERVICE_BUILDKIT_STORAGE
CEDARCI_SERVICE_DOCKER_IN_DOCKER_STORAGE
container:
variables:
CEDARCI_SERVICE_BUILDKIT_STORAGE: "20"