Build container images
These methods can be used to build a container image, at the time of writing:
Software | Ease | Security | Perf | Run location | Description |
---|---|---|---|---|---|
Azure Container Registry task, Google Cloud Build | 🟩🟩🟥 | 🟩🟩🟩 | 🟩🟩🟩 | Managed environment | A managed service build the container image in a dedicated environment. |
Kaniko | 🟩🟥🟥 | 🟩🟩🟩 | 🟩🟩🟥 | Self-hosted Kubernetes | A Pod is created for each build, taking care of building and pushing the container to the registry. No security drawbacks. |
img, BuildKit | 🟩🟩🟩 | 🟩🟩🟥 | 🟩🟥🟥 | Local CLI | CLI to build the images. Can build different architectures on a single machine. Requires Seccomp disabled and AppArmor disabled. |
Docker in docker | 🟩🟩🟩 | 🟥🟥🟥 | 🟩🟩🟩 | Local CLI | Before Kubernetes 1.20, it was possible to build container images in the agent, using the Docker socket. This is not possible anymore, as Kubernetes deprecated the Docker socket in favor of the Container Runtime Interface. |
We choose BuildKit for this project. Its license allows commercial use, and the project and mainly maintained, as the time of writing, by Docker, Netlix and Microsoft.
Linux systems are supported, but not Windows:
Ref | Container build inside of the agent with BuildKit |
---|---|
ghcr.io/clemlesne/blue-agent:bookworm-main | ✅ |
ghcr.io/clemlesne/blue-agent:bullseye-main | ✅ |
ghcr.io/clemlesne/blue-agent:focal-main | ✅ |
ghcr.io/clemlesne/blue-agent:jammy-main | ✅ |
ghcr.io/clemlesne/blue-agent:ubi8-main | ✅ |
ghcr.io/clemlesne/blue-agent:ubi9-main | ✅ |
ghcr.io/clemlesne/blue-agent:win-ltsc2019-main | ❌ |
ghcr.io/clemlesne/blue-agent:win-ltsc2022-main | ❌ |
How to use the bundled BuildKit
There are two components, the backend, buildkitd
, and the CLI, buildctl
.
Requirements:
- Setup special security requirements, you can find them in the example file
container-build.yaml
. - In the pipeline, run
buildkitd
before usingbuildctl
.
# azure-pipelines.yaml
variables:
- name: container_name
value: my-app
- name: container_registry_domain
value: my-app-registry.azurecr.io
steps:
- bash: |
# Start buildkitd
rootlesskit buildkitd --oci-worker-no-process-sandbox --addr $BUILDKIT_HOST &
# Wait for buildkitd to start
while ! buildctl debug workers; do sleep 1; done
displayName: Run BuildKit
- bash: |
buildctl build \
--frontend dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--output type=image,name=$(container_registry_domain)/$(container_name):latest,push=true
displayName: Build and push the image
Out of the box, argument --opt platform=linux/amd64,linux/arm64
can be added to build an image compatible with multiple architectures (more can be specified). Multiple cache strategies are available (including container registry, Azure Storage Blob, AWS S3).
BuildKit and the performance
BuildKit works by virtualization in the user space. You can’t expect build times as short as native (on your laptop for example). QEMU is used as a backend. This has the advantage of being able to create images for different architectures than your processor. Virtualization-wise, not all CPU models are equivalent, you can refer to the official project documentation to select the most appropriated CPU model for your Kubernetes Node Pool.