Ga naar hoofdinhoud

Docker Build Args: De ultieme gids voor dataprofessionals

Leer hoe je je containerisatieworkflow een boost geeft met Docker-buildargumenten voor flexibele, veilige en consistente omgevingen.
· 11 min lezen

Verken met AI

Heb je last van inconsistente Docker-builds binnen je developmentteam? Build-argumenten zijn misschien precies wat je zoekt. Het is een beproefde oplossing om flexibele en gestandaardiseerde Docker-images te maken. Ze laten je waarden in je buildproces injecteren zonder ze hard te coderen, waardoor je Dockerfiles draagbaarder en beter te onderhouden worden.

Docker build args lossen veelvoorkomende problemen op, zoals het omgaan met verschillende basisimages, pakketversies of configuratie-instellingen tussen omgevingen.

De officiële documentatie van Docker raadt build-argumenten aan om builds te parameteriseren, in plaats van omgevingsvariabelen daarvoor te misbruiken. Ze zijn vooral waardevol in CI/CD-pijplijnen waarin je images met verschillende configuraties moet maken vanuit dezelfde Dockerfile.

> Nieuw met Docker en containers? Volg onze gids om snel op stoom te komen.

In dit artikel laat ik je zien hoe je Docker-buildargumenten gebruikt om efficiëntere, veiligere en flexibelere containerworkflows te bouwen.

Introductie tot Docker Build Args

Build-argumenten (of build args) zijn variabelen die je tijdens het bouwen aan Docker doorgeeft, en die alleen beschikbaar zijn tijdens het construeren van de image. 

In tegenstelling tot omgevingsvariabelen die in de container blijven bestaan tijdens runtime, bestaan build-argumenten alleen binnen de context van het commando docker build en verdwijnen ze zodra je image is gemaakt. Ze werken vergelijkbaar met functieparameters: je kunt bij elke build andere waarden doorgeven.

De primaire use-cases voor build-argumenten draaien om het creëren van flexibele, herbruikbare Dockerfiles. 

Je kunt build-argumenten gebruiken om verschillende basisimages te specificeren (zoals schakelen tussen Alpine of Debian), applicatieversies in te stellen zonder je Dockerfile aan te passen, of build-time instellingen te configureren zoals proxyservers of repository-URL's. Deze flexibiliteit komt goed van pas in CI/CD-pijplijnen waarin je mogelijk dezelfde Dockerfile met verschillende parameters bouwt op basis van het deploymentdoel.

Build-argumenten schitteren in situaties waarin je builds wilt aanpassen zonder meerdere varianten van een Dockerfile te hoeven onderhouden. Ze helpen je het DRY-principe (Don't Repeat Yourself) te volgen door je containerconfiguratielogica te centraliseren, terwijl je toch kunt aanpassen. 

Ze zijn ook ideaal om verschillen tussen ontwikkel-, test- en productieomgevingen af te handelen die alleen invloed mogen hebben op hoe de image wordt gebouwd, niet op hoe de container draait.

Nu je weet wat build-argumenten zijn, laat ik je zien hoe je ze gebruikt.

Build-argumenten definiëren en gebruiken

Laten we nu praktisch aan de slag gaan met het implementeren van build-argumenten. We gaan ervan uit dat je Docker hebt geïnstalleerd en geconfigureerd.

Basis-syntaxis en scope

Je kunt build-argumenten in je Dockerfile declareren met de instructie ARG. Die kan vóór of na de instructie FROM staan, afhankelijk van wanneer je ze nodig hebt. Dit is de basis-syntaxis:

# Setting a build arg with a default value
ARG VERSION=latest

# Using the build arg
FROM ubuntu:${VERSION}

Je kunt waarden doorgeven tijdens het bouwen van de image met de vlag --build-arg:

docker build --build-arg VERSION=20.04 -t myapp:20.04 .

Image 1 - Basic Docker build args

Afbeelding 1 - Basis Docker build-argumenten

De scope van build-argumenten volgt specifieke regels die belangrijk zijn om te begrijpen. Argumenten die vóór de instructie FROM worden gedeclareerd, zijn alleen vóór FROM beschikbaar en moeten daarna opnieuw worden gedeclareerd als je ze later nodig hebt. 

Dat komt doordat elke FROM-instructie een nieuwe buildstage start met een eigen scope. Dit gedrag moet je echt onthouden, zeker bij multistage-builds.

Geavanceerde declaratietechnieken

Laten we een complete Flask-"Hello World"-applicatie maken die build-argumenten gebruikt om verschillende configuraties te ondersteunen:

> Leer hoe je een applicatie containeriseert met Docker.

Maak eerst een eenvoudige Flask-app (app.py):

from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello_world():
    return "Hello, World!"


if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

Maak hierbij ook een bestand requirements.txt aan:

flask==3.1.0

Laten we nu een Dockerfile maken die build-argumenten gebruikt voor flexibele configuratie:

# Define build arguments with default values
ARG PYTHON_VERSION=3.13
ARG ENVIRONMENT=production

# Use the PYTHON_VERSION arg in the FROM instruction
FROM python:${PYTHON_VERSION}-slim

# Redeclare args needed after FROM
ARG ENVIRONMENT
ENV FLASK_ENV=${ENVIRONMENT}

# Set working directory
WORKDIR /app

# Copy requirements file
COPY requirements.txt .

# Install dependencies based on environment
RUN if [ "$ENVIRONMENT" = "development" ]; then \
      pip install -r requirements.txt && \
      pip install pytest black; \
    else \
      pip install --no-cache-dir -r requirements.txt; \
    fi

# Copy application code
COPY . .

# Expose port
EXPOSE 5000

# Set default command
CMD ["python", "app.py"]

> Ziet de bovenstaande Dockerfile er verwarrend uit? Leer Docker vanaf nul met onze gids.

Om deze image voor development te bouwen met een specifieke Python-versie, kun je het volgende vanuit je terminal uitvoeren:

# Building for development with Python 3.11
docker build \
  --build-arg PYTHON_VERSION=3.11 \
  --build-arg ENVIRONMENT=development \
  -t flaskapp:dev .

Image 2 - Build args in a basic Python application

Afbeelding 2 - Build-argumenten in een basis Python-applicatie

In multistage-builds vereisen build-argumenten speciale behandeling. Hier is een volledig voorbeeld dat laat zien hoe je argumenten door meerdere stages heen doorgeeft met onze Flask-app:

# Dockerfile for a multi-stage build
ARG PYTHON_VERSION=3.13

# Build stage
FROM python:${PYTHON_VERSION}-slim AS builder
ARG ENVIRONMENT=production
ENV FLASK_ENV=${ENVIRONMENT}

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

COPY . .
# In a real app, you might run tests or build assets here
RUN echo "Building Flask app for ${ENVIRONMENT}"

# Production stage
FROM python:${PYTHON_VERSION}-slim
ARG ENVIRONMENT
ENV FLASK_ENV=${ENVIRONMENT}

WORKDIR /app
COPY --from=builder /usr/local/lib/python*/site-packages /usr/local/lib/python*/site-packages
COPY --from=builder /app .

# Add metadata based on build args
LABEL environment="${ENVIRONMENT}" \
      python_version="${PYTHON_VERSION}"

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

Je kunt dit nu bouwen met de specifieke Python-versie en omgeving:

docker build \
  --build-arg PYTHON_VERSION=3.12 \
  --build-arg ENVIRONMENT=staging \
  -t flaskapp:staging .

Image 3 - Build args in multi-stage builds

Afbeelding 3 - Build-argumenten in multistage-builds

Kortom, met deze aanpak houd je een consistente configuratie aan in alle stages van je build.

Voorgedefinieerde build-argumenten

Docker biedt verschillende voorgedefinieerde build-argumenten die je kunt gebruiken zonder ze eerst te declareren. Dit zijn:

  • HTTP_PROXY en HTTPS_PROXY: Handig voor builds in bedrijfsomgevingen met proxyservers.
  • FTP_PROXY: Vergelijkbaar met HTTP-proxy's maar voor FTP-verbindingen.
  • NO_PROXY: Geeft hosts op die de proxy moeten omzeilen.
  • BUILD_DATE en VCS_REF: Vaak gebruikt voor imagemetadata en versiebeheer.

Deze voorgedefinieerde argumenten zijn handig wanneer je images bouwt in omgevingen met specifieke netwerkconfiguraties. In een bedrijfsnetwerk met strikte proxy-eisen kun je bijvoorbeeld gebruiken:

docker build --build-arg HTTP_PROXY=http://proxy.example.com:8080 .

Deze aanpak houdt je Dockerfile draagbaar en toch bruikbaar in beperkte omgevingen.

Beveiligingsimplicaties en risicobeperking

Hoewel build-argumenten flexibiliteit bieden, introduceren ze ook potentiële beveiligingsrisico's die je moet begrijpen om je Docker-images veilig te houden.

Kanalen voor uitlekken van argumenten

Build-argumenten zijn niet zo privé als je misschien denkt. De waarden van build-argumenten kunnen lekken via verschillende kanalen die veel ontwikkelaars over het hoofd zien. Ten eerste onthult de Docker-imagegeschiedenis al je build-argumenten. Iedereen met toegang tot je image kan docker history uitvoeren om de waarden te zien die je tijdens de build hebt gebruikt, inclusief mogelijk gevoelige informatie zoals API-sleutels of tokens.

docker history flaskapp:dev

Image 4 - Docker history

Afbeelding 4 - Docker history

Tussentijdse lagen kunnen ook build-argumenten lekken. Zelfs als je een multistage-build gebruikt en de laag met gevoelige informatie niet kopieert, blijven de waarden van build-argumenten in de layercache op de buildmachine. Dat betekent dat iedereen met toegang tot de Docker-daemon op je buildserver deze informatie mogelijk kan achterhalen.

CI/CD-logs vormen een ander aanzienlijk risico. De meeste CI/CD-systemen loggen het volledige build-commando, inclusief eventuele build-argumenten die via de commandoregel zijn doorgegeven.

Dit volledige commando, inclusief API_KEY, is bijvoorbeeld zichtbaar in CI/CD-logs:

docker build --build-arg API_KEY=secret123 -t myapp:latest .

Deze logs zijn vaak toegankelijk voor een bredere groep ontwikkelaars of zelfs opgeslagen bij derden, wat het aanvalsoppervlak van gevoelige waarden vergroot.

Veilige alternatieven

Voor gevoelige informatie moet je de secretsfunctie van Docker BuildKit gebruiken in plaats van build-argumenten. BuildKit laat je secrets mounten tijdens het buildproces zonder ze te bewaren in de uiteindelijke image of de geschiedenis.

Hier is een voorbeeld-Dockerfile die Docker BuildKit-secrets gebruikt:

FROM python:3.13-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

# Use secret mount instead of build arg
RUN --mount=type=secret,id=api_key \
    cat /run/secrets/api_key > api_key.txt

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

Om deze image met een secret te bouwen, maak je eerst het bestand api_key.txt aan:

echo "my-secret-api-key" > api_key.txt

En bouw vervolgens de image met het secret:

DOCKER_BUILDKIT=1 docker build \
  --secret id=api_key,src=api_key.txt \
  -t flaskapp:secure .

Image 5 - Building images with BuildKit secrets

Afbeelding 5 - Images bouwen met BuildKit-secrets

Voor configuratie die tijdens runtime beschikbaar moet zijn, blijven omgevingsvariabelen de voorkeursaanpak. Je kunt ze instellen wanneer je een container start, zonder ze in de image te bakken:

# Set environment variables at runtime
docker run -e API_KEY=secret123 -p 5000:5000 flaskapp:latest

Om gevoelige configuratie in productie veilig te verwerken, kun je overwegen om containerorkestratieplatforms zoals Kubernetes te gebruiken, die veilige methoden zoals Secrets bieden voor het beheren van gevoelige informatie. Docker Swarm biedt vergelijkbare mogelijkheden met zijn secretsbeheer.

> Docker is niet het enige containerisatieplatform. Lees over Podman om te bepalen welk hulpmiddel beter bij je past.

Onthoud de vuistregel: gebruik build-argumenten voor build-time configuratie die niet gevoelig is, gebruik BuildKit-secrets voor gevoelige behoeften tijdens het bouwen, en gebruik omgevingsvariabelen of secrets van je orkestratieplatform voor runtimeconfiguratie.

Integratie met container-ecosystemen

Nu de basis duidelijk is, gaan we bekijken hoe je build-argumenten benut binnen bredere Docker-ecosystemen en moderne buildtools.

Docker Compose

Docker Compose maakt het eenvoudig om build-argumenten te definiëren en te delen over je multi-containerapplicaties.

Als je wilt meedoen, is hier een complete projectstructuur voor twee eenvoudige Flask-services:

flask-project/
├── docker-compose.yml         # Main compose configuration
├── .env                       # Environment variables for compose
├── web/
│   ├── Dockerfile             # Web service Dockerfile
│   ├── app.py                 # Flask application
│   └── requirements.txt       # Python dependencies
├── api/
│   ├── Dockerfile             # API service Dockerfile
│   ├── app.py                 # API Flask application  
│   └── requirements.txt       # API dependencies

Ik loop snel de bestandsinhoud één voor één door:

web/app.py

from flask import Flask, render_template

app = Flask(__name__)


@app.route("/")
def index():
    return render_template("index.html", title="Flask Web App")


@app.route("/about")
def about():
    return "About page - Web Service"


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

web/requirements.txt

flask==3.1.0

web/Dockerfile

# Web service Dockerfile
ARG PYTHON_VERSION=3.13

FROM python:${PYTHON_VERSION}-slim

# Redeclare the build arg to use it after FROM
ARG PYTHON_VERSION
ARG ENVIRONMENT=production

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV FLASK_ENV=${ENVIRONMENT}

WORKDIR /app

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

# Copy application code
COPY . .

# Create a simple template folder and file if not exists
RUN mkdir -p templates && \
    echo "<html><body><h1>Hello from Web Service</h1><p>Python version: ${PYTHON_VERSION}</p><p>Environment: ${ENVIRONMENT}</p></body></html>" > templates/index.html

EXPOSE 5000

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

api/app.py

from flask import Flask, jsonify

app = Flask(__name__)


@app.route("/api/health")
def health():
    return jsonify({"status": "healthy"})


@app.route("/api/data")
def get_data():
    return jsonify(
        {"message": "Hello from the API service", "items": ["item1", "item2", "item3"]}
    )


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000, debug=True)

api/requirements.txt

flask==3.1.0

api/Dockerfile

ARG PYTHON_VERSION=3.13

FROM python:${PYTHON_VERSION}-slim

# Redeclare the build arg to use it after FROM
ARG PYTHON_VERSION
ARG ENVIRONMENT=production

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV FLASK_ENV=${ENVIRONMENT}

WORKDIR /app

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

# Copy application code
COPY . .

# Add metadata label based on build args
LABEL python.version="${PYTHON_VERSION}" \
      app.environment="${ENVIRONMENT}"

EXPOSE 8000

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

.env

PYTHON_VERSION=3.10
ENVIRONMENT=development

docker-compose.yml

services:
  web:
    build:
      context: ./web
      dockerfile: Dockerfile
      args:
        PYTHON_VERSION: ${PYTHON_VERSION:-3.13}
        ENVIRONMENT: ${ENVIRONMENT:-development}
    ports:
      - "5000:5000"
    depends_on:
      - api
    
  api:
    build:
      context: ./api
      dockerfile: Dockerfile
      args:
        PYTHON_VERSION: ${PYTHON_VERSION:-3.13}
        ENVIRONMENT: ${ENVIRONMENT:-production}
    ports:
      - "8000:8000"

Kort gezegd is dit een heel eenvoudige manier om twee applicaties in geïsoleerde omgevingen tegelijk te starten, beide met een specifieke set build-argumenten.

Je kunt dit commando gebruiken om de multi-containersetup te draaien:

docker compose up --build

Image 6 - Build args with Docker Compose

Afbeelding 6 - Build-argumenten met Docker Compose

Na een paar seconden zie je dat beide services draaien:

Image 7 - Build args with Docker Compose (2)

Afbeelding 7 - Build-argumenten met Docker Compose (2)

Het is best een breedsprakige setup voor twee zulke simpele apps, maar je ziet het grote plaatje: build-argumenten staan in het compose-bestand en worden in de afzonderlijke Dockerfiles gebruikt.

Terzijde: je kunt ook variabele waarden uit je omgeving doorgeven aan build-argumenten, wat handig is voor CI/CD-pijplijnen:

services:
  web:
    build:
      context: .
      args:
        - PYTHON_VERSION=${PYTHON_VERSION:-3.10}

En om deze waarden te overschrijven wanneer je docker-compose draait, kun je omgevingsvariabelen gebruiken:

PYTHON_VERSION=3.10 docker-compose up --build

Met deze aanpak behoud je consistente builds binnen je team, terwijl je toch flexibiliteit hebt wanneer dat nodig is.

BuildKit-functies

BuildKit, de moderne build-engine van Docker, geeft je buildproces een boost met functies die het gebruik van build-argumenten nog krachtiger maken. Wanneer je BuildKit inschakelt (door DOCKER_BUILDKIT=1 te zetten), ontgrendel je een aantal nieuwe mogelijkheden.

Inline cache verbetert de buildprestaties door de buildcache van een remote image te gebruiken. Je kunt met de vlag --cache-from een bronimage als cache opgeven, en BuildKit gebruikt die lagen vervolgens slim:

DOCKER_BUILDKIT=1 docker build \
  --build-arg PYTHON_VERSION=3.10 \
  --cache-from flaskapp:dev \
  -t flaskapp:latest .

Een andere waardevolle BuildKit-functie is deterministische output, die ervoor zorgt dat je builds reproduceerbaar zijn. Dat is cruciaal wanneer je exact dezelfde image wilt, ongeacht wanneer of waar die gebouwd is:

# Build with deterministic output
DOCKER_BUILDKIT=1 docker build \
  --build-arg PYTHON_VERSION=3.10 \
  --build-arg BUILD_DATE=2025-05-01 \
  --output type=docker,name=flaskapp:stable \
  .

BuildKit's redactie van secrets in logs beschermt gevoelige informatie tijdens builds. 

In tegenstelling tot gewone build-argumenten, die in buildlogs verschijnen, verbergt BuildKit automatisch de waarden van secrets:

# Create a file with the API key
echo "my-api-key-value" > ./api-key.txt

# Build with secret (value won't appear in logs)
DOCKER_BUILDKIT=1 docker build \
  --secret id=api_key,src=./api-key.txt \
  -t flaskapp:secure .

In je Dockerfile krijg je toegang tot dit secret met:

RUN --mount=type=secret,id=api_key \
    cat /run/secrets/api_key > /app/config/api_key.txt

Deze BuildKit-functies werken samen met build-argumenten om een veiliger, efficiënter en reproduceerbaar buildsystem te creëren dat zich kan aanpassen aan vrijwel elke containerworkflow.

Best practices voor enterprise-adoptie

Het implementeren van Docker-buildargumenten in grote teams vereist gestandaardiseerde aanpakken, tenminste als je verwarring wilt minimaliseren en de beveiligings- en prestatiewinst wilt maximaliseren.

Begin bij adoptie van build-argumenten in enterprise-omgevingen met juiste validatie van argumenten. 

Geef altijd verstandige standaardwaarden voor elk build-argument, zodat builds niet onverwacht falen wanneer argumenten niet worden doorgegeven. Voeg ook validatiechecks toe in je Dockerfile om te verifiëren dat kritieke build-argumenten aan je eisen voldoen.

Hier is een voorbeeld dat de Python-versie valideert:

ARG PYTHON_VERSION=3.9
# Validate Python version
RUN if [[ ! "$PYTHON_VERSION" =~ ^3\.[0-9]+$ ]]; then \
      echo "Invalid Python version: ${PYTHON_VERSION}. Must be 3.x"; \
      exit 1; \
    fi

Optimalisatie van layercaching is cruciaal om buildtijden in CI/CD-pijplijnen te verkorten. 

Orden je Dockerfile-instructies om cachehits te maximaliseren door zelden veranderende content (zoals het installeren van dependencies) vóór vaak veranderende content (zoals applicatiecode) te plaatsen. 

Als je build-argumenten gebruikt die vaak kunnen wijzigen, plaats ze dan na stabiele stappen om te voorkomen dat je de hele cache ongeldig maakt:

FROM python:3.13-slim

WORKDIR /app

# Dependencies change less frequently - good cache utilization
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Build args that might change often come AFTER stable operations
ARG BUILD_NUMBER
ARG COMMIT_SHA
# Now these args won't invalidate the dependency cache

Metadatabeheer via build-argumenten verbetert traceerbaarheid en compliance. Gebruik build-argumenten om build-time metadata als labels in te voegen:

ARG BUILD_DATE
ARG VERSION
ARG COMMIT_SHA
ARG BUILD_URL

LABEL org.opencontainers.image.created="${BUILD_DATE}" Can you please provide me with access to this document?
      org.opencontainers.image.version="${VERSION}" \
      org.opencontainers.image.revision="${COMMIT_SHA}" \
      org.opencontainers.image.url="${BUILD_URL}"

Deze gestandaardiseerde labels volgen de specificatie van de Open Container Initiative (OCI), wat betekent dat je images compatibel zijn met verschillende containermanagementtools.

Documentatie wordt vaak over het hoofd gezien, maar is cruciaal voor enterprise-adoptie. 

Maak een duidelijke README-sectie die alle beschikbare build-argumenten documenteert, met hun doel, standaardwaarden en gebruiksvoorbeelden. Vermeld welke build-argumenten verplicht zijn en welke optioneel, en documenteer eventuele interacties tussen verschillende argumenten. Overweeg om deze informatie ook als commentaar toe te voegen aan je CI/CD-pijplijnconfiguratiebestanden, zodat ontwikkelaars begrijpen welke waarden ze moeten aanleveren:

# Example documented CI configuration
build_job:
  script:
    # BUILD_NUMBER: Unique identifier for this build (required)
    # ENVIRONMENT: Target deployment environment [dev|staging|prod] (required)
    # PYTHON_VERSION: Python version to use (optional, default: 3.9)
    - docker build
      --build-arg BUILD_NUMBER=${CI_PIPELINE_ID}
      --build-arg ENVIRONMENT=${DEPLOY_ENV}
      --build-arg PYTHON_VERSION=${PYTHON_VERSION:-3.9}
      -t myapp:${CI_PIPELINE_ID} .

Voor echte enterprise-grade adoptie kun je overwegen een schema voor build-argumenten te implementeren dat versieerbaar en valideerbaar is. Zo kun je je buildconfiguratie in de tijd doorontwikkelen en toch backward compatible blijven.

Vergelijkende analyse: Build-argumenten vs. omgevingsvariabelen

Als je veilige en flexibele Docker-images wilt maken die best practices volgen, moet je begrijpen wanneer je build-argumenten gebruikt en wanneer omgevingsvariabelen.

Hier is een tabel waar je altijd op kunt terugvallen:

Functie

Build-argumenten

Omgevingsvariabelen

Beschikbaarheid

Alleen beschikbaar tijdens het bouwen van de image

Beschikbaar tijdens zowel build als runtime van de container

Persistentie

Worden niet in de uiteindelijke image bewaard (tenzij expliciet omgezet naar ENV)

Worden in de image bewaard en zijn beschikbaar voor draaiende containers

Beveiliging

Zichtbaar in de imagegeschiedenis met docker history

Niet zichtbaar in de imagegeschiedenis maar toegankelijk voor processen binnen de container

Gebruik

Ideaal voor build-time configuratie zoals versies, buildpaden, compilerflags

Ideaal voor runtimeconfiguratie zoals verbindingsstrings, feature-flags, logniveaus

Declaratie

Gedefinieerd met de instructie ARG in de Dockerfile

Gedefinieerd met de instructie ENV in de Dockerfile of tijdens runtime

Standaardwaarden

Kunnen standaardwaarden hebben: ARG VERSION=latest

Kunnen standaardwaarden hebben: ENV MODE=production

Scope

Gescopeerd per buildstage; moet na elke FROM opnieuw worden gedeclareerd

Beschikbaar in alle buildstages en geërfd door child-images

Wijzigmethode

--build-arg tijdens het bouwen

-e of --env tijdens runtime van de container

Het belangrijkste verschil zit in timing en doel. Build-argumenten configureren het buildproces zelf, terwijl omgevingsvariabelen de draaiende applicatie configureren. Je gebruikt bijvoorbeeld een build-argument om te kiezen welk basisimage je gebruikt (ARG PYTHON_VERSION=3.10), maar een omgevingsvariabele om je applicatie te vertellen op welke poort die moet luisteren (ENV PORT=8080).

Vanuit beveiligingsperspectief vormen build-argumenten een hoger risico voor gevoelige informatie, omdat ze in de imagegeschiedenis achterblijven. 

Overweeg deze workflow voor het afhandelen van verschillende soorten configuratie:

# Build-time configuration (non-sensitive)
ARG PYTHON_VERSION=3.13
FROM python:${PYTHON_VERSION}-slim

# Build-time secrets (use BuildKit secrets)
RUN --mount=type=secret,id=build_key \
    cat /run/secrets/build_key > /tmp/key && \
    # Use the secret for build operations
    rm /tmp/key

# Runtime configuration (non-sensitive)
ENV LOG_LEVEL=info

# Runtime secrets (should be injected at runtime, not here)
# This would be provided at runtime with:
# docker run -e API_KEY=secret123 myimage

In de praktijk is een veelvoorkomend patroon om geselecteerde build-argumenten om te zetten naar omgevingsvariabelen wanneer ze tijdens runtime beschikbaar moeten zijn:

ARG APP_VERSION=1.0.0
# Make the version available at runtime
ENV APP_VERSION=${APP_VERSION}

Voor enterprise-applicaties maakt deze scheiding het mogelijk dat verschillende teams verschillende aspecten van de levenscyclus beheren. DevOps-teams kunnen build-argumenten aanpassen voor de imageconstructie, terwijl operators omgevingsvariabelen kunnen bijstellen tijdens deployment zonder images opnieuw te bouwen.

Samenvatting van Docker Build Args

Docker-buildargumenten zijn niet zomaar een technische feature - het zijn je go-to tools om images te maken die consistent werken binnen je team en omgevingen. 

Ik heb laten zien hoe je ze gebruikt in eenvoudige Python-projecten, terwijl je gevoelige informatie veilig houdt. Je hebt ook gezien hoe je build-argumenten integreert met tools zoals Docker Compose.

Zie build-argumenten als de fundering van een flexibele containerisatiestrategie. Begin klein door je Python-versie te parameteriseren in je volgende project. Als dat vertrouwd voelt, voeg dan voorwaardelijke logica toe voor verschillende omgevingen. Voor je het weet, maak je geavanceerde multistage-builds die je team kan aanpassen zonder de Dockerfile te wijzigen.

Klaar om dieper te duiken? Deze cursussen van DataCamp zijn je beste volgende stap:

FAQs

Wat zijn Docker-buildargumenten?

Docker-buildargumenten (build-argumenten) zijn variabelen die je doorgeeft aan het Docker-buildproces en die alleen beschikbaar zijn tijdens het construeren van de image. Ze laten je je Dockerfile aanpassen zonder die te wijzigen, waardoor je containerbuilds flexibeler en herbruikbaarder worden. Zie ze als parameters die je bij elke build kunt bijstellen, ideaal om met verschillende omgevingen of configuraties om te gaan.

Hoe verschillen build-argumenten van omgevingsvariabelen in Docker?

Build-argumenten bestaan alleen tijdens het bouwen van de image, terwijl omgevingsvariabelen blijven bestaan in de draaiende container. Build-argumenten worden gedefinieerd met de instructie ARG en doorgegeven via de vlag --build-arg tijdens het bouwen; ze zijn ideaal voor zaken als het kiezen van basisimages of het instellen van build-time configuraties. Omgevingsvariabelen, gedefinieerd met ENV, zijn bedoeld voor runtimeconfiguratie die je applicatie nodig heeft tijdens het draaien.

Welke beveiligingsrisico’s moet ik kennen bij het gebruik van Docker-buildargumenten?

Build-argumenten zijn niet zo privé als veel ontwikkelaars aannemen: hun waarden zijn zichtbaar in de imagegeschiedenis en in CI/CD-logs. Gebruik build-argumenten nooit voor gevoelige informatie zoals API-sleutels of wachtwoorden, want iedereen met toegang tot je image kan deze waarden zien. Gebruik voor gevoelige data in plaats daarvan Docker BuildKit-secrets, die niet in de uiteindelijke image of geschiedenis worden bewaard.

Hoe kan ik build-argumenten doorgeven via CI/CD-pijplijnen zoals GitHub Actions?

De meeste CI/CD-platforms ondersteunen Docker-buildargumenten via hun configuratiebestanden. In GitHub Actions kun je build-argumenten doorgeven in je workflow-YAML via de build-args-parameter onder de docker/build-push-action. Je kunt omgevingsvariabelen, repositorysecrets of hardgecodeerde waarden gebruiken, afhankelijk van je beveiligingsbehoeften. Zo automatiseer je builds met verschillende configuraties op basis van branch, omgeving of andere CI-variabelen.

Is er een limiet aan het aantal build-argumenten dat ik in een Dockerfile kan gebruiken?

Er is geen harde technische limiet aan het aantal build-argumenten, maar te veel maakt je Dockerfile moeilijk te begrijpen en te onderhouden. Richt je voor data science-projecten op het parametriseren van kritieke variabelen, zoals Python-versie, frameworkkeuzes of datasetconfiguraties. Als je merkt dat je meer dan 8-10 build-argumenten hebt, overweeg dan je Dockerfile op te splitsen in kleinere, meer gefocuste bestanden of Docker Compose te gebruiken om de complexiteit te beheersen.

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