Ga naar hoofdinhoud

Docker Buildx: zo bouw je multi-platform containerimages

Leer hoe Docker Buildx het traditionele bouwen van containers uitbreidt met multi-platformondersteuning, geavanceerde cachingstrategieën en prestatie-optimalisaties. Deze gids behandelt alles van basisconcepten tot geavanceerde technieken.
· 14 min lezen

Verken met AI

Containers bouwen voor meerdere platforms klinkt intimiderend en tijdrovend, maar je zult zo zien dat het dat niet is.

Het docker buildx commando lost deze uitdaging op door de bouwmogelijkheden van Docker uit te breiden met geavanceerde features zoals multi-platform imagecreatie, verbeterde caching en parallelle buildverwerking. Het integreert de next-gen build-engine BuildKit rechtstreeks in de Docker CLI. Met het buildx-commando maak je kleinere, snellere en veiligere containerimages zonder een volledig nieuw toolset te hoeven leren.

De afgelopen jaren is Buildx min of meer onmisbaar geworden voor goede DevOps-praktijken en cloud-native applicatieontwikkeling. Het stroomlijnt CI/CD-pijplijnen en helpt jou en je team om applicaties consistent te leveren over diverse deploymentdoelen, van ARM-gebaseerde IoT-apparaten tot cloudserverfarms.

> Nieuw met Docker? Onze praktische gids voor absolute beginners helpt je in no time op weg.

In dit artikel neem ik je mee door basis- en geavanceerde docker buildx-technieken.

Docker Buildx begrijpen

Je gebruikt waarschijnlijk al Docker, dus je kent het standaard docker build-commando. Vroeg of laat gaat dat echter beperkend aanvoelen, zeker wanneer je projecten complexer worden.

> Docker Buildx gaat ervan uit dat Docker is geïnstalleerd. Als dat niet zo is en je draait Linux, volg dan deze gids voor een eenvoudige installatie.

Docker Buildx geeft je een verbeterde build-ervaring die aansluit op je bestaande kennis. Het is geen aparte tool die je moet installeren — het zit al gebundeld bij Docker Desktop en Engine sinds versie 19.03. Buildx gebruikt onder de motorkap BuildKit, Docker’s next-gen builder die het maken van images opnieuw uitdenkt. Je merkt snellere builds, kleinere images en ondersteuning voor extra features.

De sprong van docker build naar docker buildx build lijkt klein — het is tenslotte maar één woord — maar de mogelijkheden die je ermee wint zijn enorm.

Laten we bekijken hoe Buildx daadwerkelijk werkt en wat het anders maakt dan de legacy builder.

Architecturale basis van Buildx

De magie van Buildx komt voort uit het slimme client-serverontwerp.

Als je een Buildx-commando draait, gebruik je de Docker CLI als client die communiceert met de BuildKit-daemon — de servercomponent die het zware werk doet. Deze scheiding laat BuildKit dingen doen die de legacy builder niet kan, zoals buildstappen parallel uitvoeren in plaats van sequentieel. Je Dockerfile-instructies hoeven niet langer na elkaar te lopen, wat de buildtijd flink verkort als je onafhankelijke stages hebt.

Het client-servermodel maakt ook remote build-executie mogelijk. Je kunt je lokale Docker CLI richten op een externe BuildKit-instance die overal draait — op een zware buildserver, in de cloud of zelfs in een Kubernetes-cluster. Deze flexibiliteit betekent dat je je laptop niet hoeft vast te leggen voor enorme builds of je zorgen te maken over architectuurcompatibiliteit.

Dankzij het modulaire ontwerp van BuildKit kun je ook verschillende frontend-parsers inpluggen. De Dockerfile-syntaxis is de standaard, maar je kunt alternatieve builddefinities gebruiken als die beter bij je workflow passen.

Buildprocesverloop

Wanneer je docker buildx build draait, selecteert de CLI eerst een builderinstance, standaard of door jou opgegeven. Je buildcontext en Dockerfile worden naar de BuildKit-daemon gestuurd, die de instructies parseert en een gerichte acyclische graaf (DAG) van buildstappen maakt. In tegenstelling tot de legacy builder die elke instructie sequentieel afhandelt, analyseert BuildKit deze graaf om te bepalen welke stappen parallel kunnen draaien.

De builder voert die stappen vervolgens uit met efficiënte caching-algoritmes die veel slimmer zijn dan de oude laaggebaseerde cache. BuildKit volgt de exacte inputs en outputs van elke stap, waardoor onnodige herbuilds worden vermeden wanneer er niets relevants is gewijzigd. Het ondersteunt ook het verdelen van de build over meerdere workernodes voor nog snellere verwerking.

Na het bouwen kan Buildx de resultaten in verschillende formaten exporteren, niet alleen als Dockerimages. Je kunt outputten naar OCI-formaten, lokale mappen of tarballs, of zelfs het maken van een image helemaal overslaan als je alleen het buildproces wilt testen.

Klopt — dit onderdeel zou zeker baat hebben bij meer praktische voorbeelden en visuals om te laten zien hoe Buildx in de praktijk werkt. Zo zou ik het versterken met meer codevoorbeelden en suggesties voor afbeeldingen:

Kernfunctionaliteit en features

Docker Buildx draait niet alleen om sneller images bouwen, al doet het dat zeker. Het gaat erom je buildpijplijnen uit te breiden met nieuwe mogelijkheden.

Laten we duiken in de opvallende features die Buildx de moeite waard maken voor je volgende project.

> Op zoek naar Docker-projectideeën? Deze 10 zetten je DevOps-portfolio op scherp.

Gebruikte Python-applicatie

Voor dit artikel heb ik een eenvoudige Python Flask-applicatie gemaakt. Maak om mee te doen 3 bestanden aan — app.py, requirements.txt en Dockerfile.

Dit zijn de inhoudelijke voorbeelden per bestand:

app.py

from flask import Flask, render_template_string
import platform
import socket
import psutil
import datetime

app = Flask(__name__)


@app.route("/")
def home():
    html = """
    <!DOCTYPE html>
    <html>
      <head>
        <title>Docker Buildx Python Demo</title>
        <style>
          body {
            
            max-width: 800px;
            
            
          }
          .container {
            border: 1px solid #ddd;
            border-radius: 5px;
            
            background-
          }
          .info {
            
          }
          .platform {
            font-weight: bold;
            
          }
        </style>
      </head>
      <body>
        <h1>Docker Buildx Multi-Platform Demo (Python)</h1>
        <div class="container">
          <div class="info">Hostname: {{ hostname }}</div>
          <div class="info">Platform: <span class="platform">{{ os_platform }} ({{ architecture }})</span></div>
          <div class="info">CPUs: {{ cpu_count }}</div>
          <div class="info">Total Memory: {{ memory_mb }} MB</div>
          <div class="info">Server Time: {{ server_time }}</div>
        </div>
      </body>
    </html>
    """
    return render_template_string(
        html,
        hostname=socket.gethostname(),
        os_platform=platform.system(),
        architecture=platform.machine(),
        cpu_count=psutil.cpu_count(),
        memory_mb=round(psutil.virtual_memory().total / (1024 * 1024)),
        server_time=datetime.datetime.now().isoformat(),
    )


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

requirements.txt

flask==3.1.0
psutil==7.0.0

Dockerfile

FROM python:3.13-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

EXPOSE 5000

CMD ["python", "app.py"]

Als je klaar bent, open je een nieuw terminalvenster en navigeer je naar de projectmap.

Multi-platform images bouwen

Images bouwen die werken op verschillende CPU-architecturen klinkt als een nachtmerrie, maar Buildx maakt het verrassend eenvoudig.

Kijk eens naar dit commando:

docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .

Afbeelding 1 - Docker Buildx gebruiken

Afbeelding 1 - Docker Buildx gebruiken

Kortom, hiermee maak je tegelijk images voor meerdere architecturen. Buildx doet dat op drie slimme manieren: het kan QEMU gebruiken voor architectuuremulator (waardoor je ARM-images op een x86-machine kunt bouwen), verbinden met native buildernodes voor elk doelplatform, of beide combineren voor optimale prestaties. Het resultaat is een multi-architectuur manifestlijst — ook wel een "fat manifest" — die varianten van je image voor elk platform bevat.

Als je uitrolt naar diverse omgevingen zoals AWS Graviton-instances, Raspberry Pi-clusters of gemengde infrastructuur, is deze multi-platformondersteuning cruciaal.

Verbeterde cachingstrategieën

Buildx verandert caching volledig en maakt je builds over het algemeen sneller.

Het systeem implementeert een drietraps cachingstrategie die verder gaat dan eenvoudige laagcaching van traditionele Dockerbuilds:

  1. Inline cache-insluiting: Eerst gebruikt Buildx een inline cache die in je images is ingebed, zodat je gecachte lagen van eerdere builds kunt benutten, zelfs in schone omgevingen.
  2. Lokale buildcache: Ten tweede ondersteunt het een lokale buildcache die slim wordt beheerd op basis van de inputs van buildinstructies in plaats van alleen hun volgorde.
  3. Registry-gebaseerde caching: Ten derde biedt het caching via een registry, zodat je buildcache tussen machines kunt delen — perfect voor CI/CD of gedistribueerde teams.

Met onze Python-app bekijken we hoe we lokale cachingstrategieën kunnen gebruiken:

# Maak een map voor lokale cache
mkdir -p buildx-cache

# Eerste build - exporteer cache naar lokale map
docker buildx build --cache-to type=local,dest=./buildx-cache -t myapp:latest .

# Breng een kleine wijziging aan in app.py
echo "# Small comment change" >> app.py

# Tweede build - gebruik de lokale cache
docker buildx build --cache-from type=local,src=./buildx-cache -t myapp:latest .

De tweede build zal veel sneller zijn omdat hij de gecachte lagen van de eerste build hergebruikt.

Afbeelding 2 - Lokale cachingstrategieën

Afbeelding 2 - Lokale cachingstrategieën

Je kunt ook inline caching gebruiken, waarmee cachemetadata in het image zelf wordt opgenomen:

docker buildx build --cache-to type=inline -t myapp:latest .

Je configureert deze cachebackends met eenvoudige flags zoals --cache-to en --cache-from, die verwijzen naar lokale mappen, registry-repositories of zelfs gespecialiseerde cacheservices. Zo blijven je builds in verschillende omgevingen snel zonder in te leveren op reproduceerbaarheid.

Beveiligingsfeatures

Buildx bevat tools die je securityzorgen wegnemen.

Stel, je Python-app moet tijdens het buildproces een weer-API benaderen. In plaats van je API-sleutel hardcoded in de Dockerfile te zetten, kun je buildsecrets gebruiken:

# Sla je API-sleutel op in een lokaal bestand
echo "abc123yourweatherapikey" > ./api_key.txt

# Build met het secret
docker buildx build --secret id=weather_api_key,src=./api_key.txt -t myapp:latest .

In je Dockerfile kun je het secret alleen wanneer nodig benaderen:

FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
# Maak tijdens de build een configbestand met het secret
RUN --mount=type=secret,id=weather_api_key \
    echo "WEATHER_API_KEY=$(cat /run/secrets/weather_api_key)" > .env
EXPOSE 5000
CMD ["python", "app.py"]

Je kunt verifiëren dat de API-sleutel niet in het uiteindelijke image staat door de imagegeschiedenis te controleren of door te draaien:

docker run --rm myapp:latest cat .env

Afbeelding 3 - Omgaan met omgevingsvariabelen

Afbeelding 3 - Omgaan met omgevingsvariabelen

In je app.py kun je de API-sleutel zo laden:

import os
from dotenv import load_dotenv

load_dotenv()  # Load variables from .env file
api_key = os.getenv("WEATHER_API_KEY", "")
# ...

Deze aanpak betekent dat je gevoelige API-sleutel alleen beschikbaar is tijdens de specifieke buildstap waar die nodig is, maar niet in een van de imagelagen wordt opgeslagen. Wie je image binnenhaalt, kan je sleutel niet achterhalen, zelfs niet door de lagen te inspecteren.

Voor extra veiligheid kun je ook tijdelijke buildcontainers gebruiken die na de build automatisch worden verwijderd:

docker buildx build --secret id=weather_api_key,src=./api_key.txt --rm -t myapp:latest .

De --rm-vlag zorgt ervoor dat alle tussenliggende containers die tijdens het buildproces worden aangemaakt, worden verwijderd — dit verkleint het risico op gelekte credentials verder.

Operationele configuratie

Buildx inrichten voor je workflow kost maar een paar commando’s, maar de opties begrijpen helpt je er het meeste uit te halen.

Laten we bekijken hoe je Buildx lokaal kunt configureren en beheren, afgestemd op jouw behoeften.

Beheer van builderinstances

Docker Buildx gebruikt het concept van "builders" — aparte BuildKit-instances met verschillende mogelijkheden en configuraties. Je kunt meerdere builders maken voor verschillende doelen.

Kijk eerst welke builders je al hebt:

docker buildx ls

Je ziet output zoals dit:

Afbeelding 4 - Beschikbare builders

Afbeelding 4 - Beschikbare builders

Maak een nieuwe builderinstance met de volgende commando’s:

# Maak een nieuwe builder
docker buildx create --name mybuilder

# Schakel over naar die builder
docker buildx use mybuilder

# Bootstrap de builder (starten)
docker buildx inspect --bootstrap

Je controleert de werking met:

# Controleer de status
docker buildx ls

Afbeelding 5 - Overschakelen naar een aangepaste builder

Afbeelding 5 - Overschakelen naar een aangepaste builder

Moet je een builder verwijderen, draai dan:

docker buildx rm mybuilder

Output afhandelen

Buildx geeft je flexibele opties voor wat je doet met de images die je bouwt. Je kunt ze direct in je lokale Docker-daemon laden, als tarball exporteren of opslaan naar een lokale map.

Zo gebruik je deze opties met onze Python-app:

# Laad het image direct in Docker (standaardgedrag)
docker buildx build --load -t myapp:latest .

# Exporteer het image als tarball
docker buildx build --output type=docker,dest=myapp.tar -t myapp:latest .

# Sla de image-inhoud op naar een lokale map
docker buildx build --output type=local,dest=./image-output -t myapp:latest .

Na exporteren als tarball kun je het in Docker laden met:

docker load < myapp.tar

Afbeelding 6 - Een image laden vanuit een tarballexport

Afbeelding 6 - Een image laden vanuit een tarballexport

De output naar een lokale map is vooral handig voor inspectie. Dit wordt er aangemaakt:

ls -la ./image-output

Je ziet het ruwe image-bestandssysteem:

Afbeelding 7 - Inhoud van export naar lokale map

Afbeelding 7 - Inhoud van export naar lokale map

Je kunt zelfs specifieke buildstages draaien zonder een eindimage te maken. Handig voor debuggen of teststappen:

# Maak een multi-stage Dockerfile
cat > Dockerfile.multi << 'EOF'
FROM python:3.13-slim AS base
WORKDIR /app
COPY requirements.txt .

FROM base AS dev-deps
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install pytest

FROM base AS prod-deps
RUN pip install --no-cache-dir -r requirements.txt

FROM prod-deps AS final
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]
EOF

# Bouw alleen de dev-deps stage en exporteer het bestandssysteem
docker buildx build --file Dockerfile.multi --target dev-deps --output type=local,dest=./dev-deps-output .

Nu kun je inspecteren welke packages in de ontwikkelomgeving zijn geïnstalleerd:

cat ./dev-deps-output/usr/local/lib/python3.13/site-packages/pytest/__init__.py

Afbeelding 8 - Bestandsinhoud uit dev-deps-stage

Afbeelding 8 - Bestandsinhoud uit dev-deps-stage

Samengevat: deze outputopties geven je volledige controle over waar je gebouwde images terechtkomen, of je nu lokaal debugt of images voorbereidt om te delen met je team.

Geavanceerde use-cases

Tot nu toe liet ik je basiscommando’s en use-cases van Buildx zien. Buildx kan nog veel meer, met features die met de klassieke builder onmogelijk zijn.

Laten we een paar geavanceerde technieken verkennen om je containerworkflow naar een hoger niveau te tillen.

Optimalisatie van multi-stage builds

Multi-stage builds zijn een van de krachtigste Dockerfeatures om efficiënte images te maken, en Buildx maakt ze nog beter.

Ter demonstratie maken we een geoptimaliseerde Python-applicatie met meerdere stages:

# Dockerfile.optimized
FROM python:3.13-slim AS base
WORKDIR /app
COPY requirements.txt .

FROM base AS builder
RUN pip install --no-cache-dir --target=/install -r requirements.txt

FROM base AS linter
COPY --from=builder /install /usr/local/lib/python3.13/site-packages
COPY app.py .
RUN pip install pylint && pylint app.py || exit 0

FROM base AS tester
COPY --from=builder /install /usr/local/lib/python3.9/site-packages
COPY app.py .
RUN pip install pytest && python -m pytest app.py -v || exit 0

FROM python:3.13-alpine AS final
WORKDIR /app
COPY --from=builder /install /usr/local/lib/python3.13/site-packages
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]

Met Buildx kun je dit efficiënter bouwen:

docker buildx build --file Dockerfile.optimized -t myapp:optimized --load .

Afbeelding 9 - Multi-stage builds

Afbeelding 9 - Multi-stage builds

Wat maakt dit bijzonder? Buildx verwerkt onafhankelijke stages parallel. Waar de legacy builder elke stage sequentieel uitvoert, ziet Buildx dat de linter en tester-stages niet van elkaar afhankelijk zijn en ze tegelijk kan bouwen.

Een extra voordeel van deze bouwoptimalisatie is reductie van bestandsgrootte. Je kunt de imagegrootte verifiëren met:

docker images myapp

Je ziet iets als dit:

Afbeelding 10 - Docker imagegroottes

Afbeelding 10 - Docker imagegroottes

Het op Alpine gebaseerde eindimage is veel kleiner.

Integratie in CI/CD-pijplijnen

Ook al werk je lokaal, je kunt Buildx-configuraties opzetten die je CI/CD-omgeving weerspiegelen.

Begin met een .dockerignore-bestand om builds schoon te houden:

.git
__pycache__
*.pyc
*.pyo
*.pyd
.Python
env
venv
*.so
.coverage
htmlcov

Maak daarna een buildscript dat lijkt op wat je CI-pijplijn doet:

#!/bin/bash
# build.sh - Lokale CI/CD-simulatie

echo "Starting CI/CD build process..."

# Builder instellen met emulatieondersteuning
echo "Setting up builder..."
docker buildx create --name cibuilder --use || true
docker buildx inspect --bootstrap

# Linting uitvoeren
echo "Running lint stage..."
docker buildx build --file Dockerfile.optimized --target linter .

# Tests uitvoeren
echo "Running test stage..."
docker buildx build --file Dockerfile.optimized --target tester .

# Bouwen voor meerdere platforms
echo "Building multi-platform image..."
docker buildx build --file Dockerfile.optimized \
  --platform linux/amd64,linux/arm64 \
  --tag myapp:$(date +%Y%m%d) \
  --tag myapp:latest \
  --load \
  --progress=plain \
  .

echo "Build process complete!"

In gewone taal doet dit script het volgende:

  • Maakt een dedicated builder voor CI/CD.
  • Draait de lintingstage.
  • Draait de teststage.
  • Bouwt het uiteindelijke multi-platform image met versietags.

En nu het leuke deel — maak het script uitvoerbaar en draai het:

chmod +x build.sh
./build.sh

Lokaal bewerken

Een veelvoorkomende frustratie met Docker is dat je bij iedere broncodewijziging het image opnieuw moet bouwen en de container starten. Dat kost gewoon te veel tijd.

Goed nieuws: voor lokale ontwikkeling met snellere iteraties kun je een ontwikkelversie maken:

# Dockerfile.dev
FROM python:3.13-slim
WORKDIR /app

RUN pip install flask psutil python-dotenv

# Ontwikkeltools installeren
RUN pip install pytest pylint watchdog

# Mount applicatiecode tijdens runtime in plaats van kopiëren
CMD ["python", "app.py"]

Draai deze met een volumemount voor live herladen van code:

docker buildx build -f Dockerfile.dev -t myapp:dev --load .
docker run -it --rm -p 5000:5000 -v $(pwd):/app myapp:dev

Je kunt nu lokaal je app.py-bestand bewerken en de wijzigingen zijn direct zichtbaar in de draaiende container!

Hierna bespreken we prestaties.

Prestatie-overwegingen

Niemand houdt van een trage ontwikkelworkflow, en de kracht van parallelisatie met Docker Buildx kan helpen.

Laten we verkennen hoe je je builds optimaliseert en profiteert van de prestatiefeatures van Buildx om sneller images te maken.

Technieken voor buildparallelisatie

Een van de grootste voordelen van Buildx is dat het stages parallel kan bouwen. De traditionele Dockerbuilder voert elke stap sequentieel uit, maar Buildx analyseert je Dockerfile en ziet welke stappen tegelijk kunnen draaien.

Om dat te laten zien, gebruik ik twee bestanden — Dockerfile.standard en Dockerfile.parallel. Dit zijn de inhoudelijke voorbeelden van beide:

Dockerfile.standard

FROM python:3.13-slim
WORKDIR /app

# Systeemafhankelijkheden
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    g++ \
    && rm -rf /var/lib/apt/lists/*

# Python-afhankelijkheden
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Applicatiecode
COPY app.py .

# Linting
RUN pip install pylint && pylint app.py || true

EXPOSE 5000
CMD ["python", "app.py"]

Dockerfile.parallel

FROM python:3.13-slim AS python-base
WORKDIR /app

# Onafhankelijke stage voor installatie van systeemafhankelijkheden
FROM python-base AS system-deps
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    g++ \
    && rm -rf /var/lib/apt/lists/*

# Onafhankelijke stage voor installatie van Python-afhankelijkheden
FROM python-base AS python-deps
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Onafhankelijke stage voor statische code-analyse
FROM python-deps AS linting
COPY app.py .
RUN pip install pylint && pylint app.py || true

# Eindstage die afhankelijkheden combineert
FROM python-base AS final
# Kopieer vanuit system-deps stage
COPY --from=system-deps /usr/bin/gcc /usr/bin/gcc
# Kopieer vanuit python-deps stage
COPY --from=python-deps /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]

Laten we meten hoe deze parallelle structuur de buildtijd verbetert:

# Meet de standaard sequentiële build
time docker build -t myapp:standard -f Dockerfile.standard .

# Meet de parallel geoptimaliseerde build met Buildx
time docker buildx build --load -t myapp:parallel -f Dockerfile.parallel .

Ter referentie: de standaardbuild duurde 18,48 seconden, terwijl de parallelle build slechts 1,17 seconde duurde!

Voor nog betere prestaties kun je de flags --cache-from en --cache-to gebruiken om lokale schijfcaching te benutten:

# Eerste build - maak cache aan
docker buildx build --load -t myapp:latest --cache-to type=local,dest=./buildcache .

# Volgende builds - gebruik cache
docker buildx build --load -t myapp:latest --cache-from type=local,src=./buildcache .

Je kunt ook de contextgrootte beperken met zorgvuldig opgestelde .dockerignore-bestanden:

# Maak een uitgebreide .dockerignore
cat > .dockerignore << 'EOF'
.git
.github
.dockerignore
.pytest_cache
__pycache__
*.pyc
*.pyo
*.pyd
.Python
venv
env
node_modules
.coverage
htmlcov
.DS_Store
EOF

Kortom: door je Dockerfiles op te zetten met parallelisatie in gedachten en gebruik te maken van de geavanceerde caching van Buildx, wacht je minder op builds en besteed je meer tijd aan features ontwikkelen.

Ecosysteemintegratie

Docker Buildx staat niet op zichzelf. Het is gemaakt om naadloos te integreren met andere tools in je ontwikkelomgeving.

Laten we bekijken hoe Buildx samenwerkt met lokale ontwikkeltools en je containerworkflow efficiënter maakt.

Kubernetes-buildclusters

Kubernetes biedt krachtige mogelijkheden om gedistribueerde Docker Buildx-operaties over een cluster te draaien. Door Buildx met Kubernetes te integreren, krijg je snellere en veerkrachtigere builds die met je project mee opschalen.

> Nieuw met Kubernetes? De post Kubernetes vs Docker: verschillen die elke developer moet kennen is je volgende halte.

Kubernetes gebruiken voor je buildinfrastructuur biedt diverse voordelen:

  1. Automatische schaalbaarheid: Kubernetes kan je buildernodes op- of afschalen op basis van vraag en resources efficiënt toewijzen. Je kunt zelfs autoscalingregels instellen op CPU-gebruik.
  2. Resource-optimalisatie: Kubernetes-scheduling zorgt dat je builds de benodigde resources krijgen zonder individuele nodes te overbelasten. Je kunt limieten en requests instellen voor consistente prestaties.
  3. Hoge beschikbaarheid: Door BuildKit-instances over meerdere nodes te verdelen, blijft je buildinfrastructuur beschikbaar, zelfs als er nodes uitvallen.
  4. Consistente omgevingen: Iedereen in het team koppelt naar dezelfde buildinfrastructuur, waardoor "works on my machine"-problemen verdwijnen.
  5. Parallelle uitvoering: Complexe builds met veel stages kunnen parallel over meerdere nodes draaien, wat de buildtijd flink reduceert. Een project dat lokaal 15 minuten duurt, kan gedistribueerd in 3–4 minuten klaar zijn.

Beschouw dit als een meer "theoretisch" onderdeel, want dieper ingaan op Kubernetes is op zichzelf al een geavanceerd onderwerp.

Begin met een bestand buildkit-deployment.yaml met de volgende inhoud:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: buildkit
  namespace: buildkit
spec:
  replicas: 3
  selector:
    matchLabels:
      app: buildkit
  template:
    metadata:
      labels:
        app: buildkit
    spec:
      containers:
      - name: buildkit
        image: moby/buildkit:latest
        args:
        - --addr
        - tcp://0.0.0.0:1234
        ports:
        - containerPort: 1234
        securityContext:
          privileged: true
---
apiVersion: v1
kind: Service
metadata:
  name: buildkit
  namespace: buildkit
spec:
  type: ClusterIP
  ports:
  - port: 1234
    targetPort: 1234
  selector:
    app: buildkit

Voer dit bestand vervolgens uit op je Kubernetes-cluster:

kubectl create namespace buildkit
kubectl apply -f buildkit-deployment.yaml

Maak tot slot vanaf je lokale machine verbinding met deze deployment:

docker buildx create --name k8s-builder \
  --driver remote \
  --driver-opt endpoint=tcp://<cluster-ip>:1234 \
  --use

En dat is het — je bent klaar om te gaan!

IDE-plug-inondersteuning

IDE’s zoals Visual Studio Code bieden uitstekende integratie met Docker Buildx via de Docker-extensie. Zo beheer je je Buildx-workflows makkelijker rechtstreeks vanuit je ontwikkelomgeving.

Om te beginnen met Docker Buildx in VS Code, installeer je de "Docker"-extensie uit de VS Code-marktplaats.

Na installatie krijg je diverse Buildx-specifieke features:

  • Rechtsklik op een Dockerfile voor een contextmenu met de optie "Build Image..." die Buildx ondersteunt.
  • Toegang tot buildarguments, platformdoelen en outputopties via de UI.
  • Mogelijkheid om verschillende builderinstances te beheren en daartussen te wisselen.
  • Integratie met de VS Code-terminal voor het draaien van complexe Buildx-commando’s.

Afbeelding 12 - Docker-extensie voor VSCode

Afbeelding 11 - Docker-extensie voor VSCode

Hier is een voorbeeld van het aanpassen van VS Code-taken om Buildx te gebruiken door een bestand .vscode/tasks.json te maken:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Docker: Buildx Build",
      "type": "shell",
      "command": "docker buildx build --load -t ${input:imageName} .",
      "group": {
        "kind": "build",
        "isDefault": true
      }
    },
    {
      "label": "Docker: Buildx Multi-Platform",
      "type": "shell",
      "command": "docker buildx build --platform linux/amd64,linux/arm64 -t ${input:imageName} ."
    }
  ],
  "inputs": [
    {
      "id": "imageName",
      "description": "Image name (with tag):",
      "default": "myapp:latest",
      "type": "promptString"
    }
  ]
}

Met deze configuratie heb je snel toegang tot veelvoorkomende Buildx-commando’s via het Tasks-menu in VS Code (Terminal > Run Task). De extensie levert ook handige syntax highlighting voor Dockerfiles en autocompletion voor veelgebruikte Dockercommando’s, wat je Buildx-workflow productiever maakt.

Troubleshooting en debuggen

Elk ontwikkeltool heeft soms (te vaak) troubleshooting nodig, en Docker Buildx is geen uitzondering. In dit onderdeel laat ik je een paar veelvoorkomende issues zien, zodat je ze snel zelf kunt diagnosticeren en verder kunt.

Veelvoorkomende issues en oplossingen

Bij het werken met Buildx kun je een paar veelvoorkomende uitdagingen tegenkomen. Dit zijn de meest frequente issues en hun oplossingen:

  • Aanmaken van builder faalt. Krijg je fouten bij docker buildx create, check dan je Docker-versie:
docker version

Buildx vereist Docker 19.03 of nieuwer. Gebruik je een oudere versie, upgrade dan Docker om Buildx-features te gebruiken.

Krijg je "no such plugin"-fouten, controleer dan of Buildx correct is geïnstalleerd met:

docker buildx version
  • Fouten bij multi-platform builds. Bij fouten als "exec format error" of "no matching manifest" tijdens multi-platform builds, check of QEMU is geïnstalleerd:
docker buildx inspect --bootstrap

Installeer indien nodig platformemulators:

docker run --privileged --rm tonistiigi/binfmt --install all
  • Cache-gerelateerde issues. Bij problemen met caching kun je je lokale buildcache opschonen:
# Verwijder cache van een specifieke builder
docker buildx prune -b mybuilder

# Verwijder alle buildcache
docker buildx prune --all

> Wat doet het Docker prune-commando precies? Leer het met veel hands-on voorbeelden.

  • Problemen met verbinding naar de BuildKit-daemon. Zie je "failed to solve" of verbindingsfouten, herstart dan de builder:
docker buildx rm mybuilder
docker buildx create --name mybuilder --use
docker buildx inspect --bootstrap
  • Prestatieproblemen. Bij trage builds kun je de debugoutput gebruiken om bottlenecks te vinden:
docker buildx build --progress=plain --no-cache .

Deze uitgebreide output helpt te achterhalen welke buildstages het meest tijd kosten, zodat je je Dockerfile gericht kunt optimaliseren.

  • Fouten bij "load"-commando. Krijg je "error: docker exporter does not currently support exporting manifest lists" bij --load met multi-platform builds, onthoud dan dat het tegelijk laden van meerdere platforms in de Docker-daemon niet wordt ondersteund. In plaats daarvan:
# Bouw voor je huidige platform en laad het
docker buildx build --platform linux/amd64 --load -t myapp:latest .
  • Debugpraktijken. Voor complexere issues helpen deze debugaanpakken:
# Schakel BuildKit-debuglogs in
BUILDKIT_DEBUG=1 docker buildx build .

# Inspecteer de interne status van de builder
docker buildx inspect

# Check systeemeisen
docker info

# Bouw alleen tot de problematische stage
docker buildx build --target problem-stage .

# Verifieer je Dockercontext
docker context ls

Door deze troubleshootingstappen systematisch te doorlopen, los je de meeste Buildx-issues op en houd je een efficiënte containerbuildworkflow in stand.

Samenvatting van de Docker Buildx-gids

We hebben veel behandeld in dit Docker Buildx-artikel! Je hebt gezien hoe deze krachtige tool je containerbuilds sneller en flexibeler maakt.

Onthoud de belangrijkste voordelen: je kunt met één commando images voor meerdere platforms bouwen, je builds versnellen met geavanceerde caching en je images veilig houden met goed secretbeheer. De prestatieverbeteringen zijn echt, vooral als je je Dockerfiles zo structureert dat parallel bouwen mogelijk is.

Ik gebruik het voortdurend op mijn MacBook met M-chip, omdat niet alle images beschikbaar zijn voor ARM.

Of je nu solodeveloper bent of onderdeel van een groot team, Buildx biedt tools die bij je workflow passen. Je kunt lokaal bouwen, builds over containers verdelen of zelfs opschalen naar Kubernetes-clusters naarmate je behoeften groeien.

Wil je meer leren over Docker en Docker Buildx, dan raad ik de volgende DataCamp-cursussen aan:

Dario Radečić

Auteur

Dario Radečić

Senior Data Scientist, gevestigd in Kroatië. Top Tech-schrijver met meer dan 700 gepubliceerde artikelen en meer dan 10 miljoen weergaven. Auteur van het boek Machine Learning Automation with TPOT.

Onderwerpen

Gerelateerd