Lernpfad
Docker Build Args: Der ultimative Leitfaden für Datenexperten
Hast du mit inkonsistenten Docker-Builds in deinem Entwicklungsteam zu kämpfen? Bauargumente könnten das sein, wonach du suchst. Sie sind die beste Lösung, um flexible und standardisierte Docker-Images zu erstellen. Sie ermöglichen es dir, Werte in deinen Build-Prozess einzubauen, ohne siefest zu kodieren, was deine Dockerdateien portabel und wartbar macht.
Docker-Build-Args lösen häufige Probleme, wie z.B. den Umgang mit unterschiedlichen Basis-Images, Paketversionen oder Konfigurationseinstellungen in verschiedenen Umgebungen.
In der offiziellen Dokumentation von Docker wird empfohlen, Build-Args für die Parametrisierung von Builds zu verwenden, anstatt Umgebungsvariablen zu missbrauchen. Sie sind besonders wertvoll in CI/CD-Pipelines, in denen du Images mit verschiedenen Konfigurationen aus demselben Dockerfile erstellen musst.
> Neu bei Docker und Containerns? Folge unserem Leitfaden, um schnell auf Touren zu kommen.
In diesem Artikel zeige ich dir, wie du Docker-Build-Argumente verwenden kannst, um effizientere, sicherere und flexiblere Containerisierungs-Workflows zu erstellen.
Einführung in Docker Build Args
Build-Argumente (oder Build-Args) sind Variablen, diedu Docker zur Build-Zeit übergibst und die nur während des Image-Erstellungsprozesses verfügbar sind.
Im Gegensatz zu Umgebungsvariablen, die zur Laufzeit im Container bestehen bleiben, existierenBuild-Args nur im Kontext des docker build
Befehls und verschwinden, sobald dein Image erstellt wurde. Sie funktionieren ähnlich wie Funktionsparameter und ermöglichen es dir, jedes Mal, wenn du ein Bild erstellst, andere Werte einzugeben.
Die Hauptanwendungsfälle für Build-Args drehen sich um die Erstellung flexibler, wiederverwendbarer Dockerfiles.
Du kannst Build-Args verwenden, um verschiedene Basis-Images festzulegen (z. B. zwischen Alpine und Debian zu wechseln), Anwendungsversionen festzulegen, ohne dein Dockerfile zu ändern, oder Build-Zeit-Einstellungen wie Proxy-Server oder Repository-URLs zu konfigurieren. Diese Flexibilität kommt handy in CI/CD-Pipelines zum Tragen, in denen du dieselbe Dockerdatei mit unterschiedlichen Parametern je nach Verteilungsziel erstellen kannst.
Build-Args eignen sich hervorragend für Situationen, in denen du deine Builds anpassen musst, ohne mehrere Dockerfile-Varianten zu pflegen. Sie helfen dir, das DRY-Prinzip (Don't Repeat Yourself) zu befolgen, indem sie deine Container-Konfigurationslogik zentralisieren und gleichzeitig Anpassungen ermöglichen.
Sie eignen sich auch perfekt für den Umgang mit Unterschieden zwischen Entwicklungs-, Test- und Produktionsumgebungen, die sich nur darauf auswirken sollten, wie das Image erstellt wird, nicht aber, wie der Container läuft.
Da du jetzt weißt, was Build-Args sind, zeige ich dir, wie du sie verwenden kannst.
Definieren und Verwenden von Bauargumenten
Jetzt wollen wir uns die Hände schmutzig machen mit den praktischen Aspekten der Implementierung von Build-Argumenten. Es wird angenommen, dass duDocker installiert und konfiguriert hast.
Grundlegende Syntax und Umfang
Du kannst Build-Argumente in deinem Dockerfile mit der Anweisung ARG
deklarieren, die vor oder nach der Anweisung FROM
erscheinen kann, je nachdem, wann du sie verwenden musst. Hier ist die grundlegende Syntax:
# Setting a build arg with a default value
ARG VERSION=latest
# Using the build arg
FROM ubuntu:${VERSION}
Du kannst Werte angeben, wenn du das Bild mit dem --build-arg
Flag erstellst:
docker build --build-arg VERSION=20.04 -t myapp:20.04 .
Abbildung 1 - Grundlegende Docker Build-Argumente
Der Umfang der Build-Args folgt bestimmten Regeln, die du unbedingt verstehen musst. Args, die vor der Anweisung FROM
deklariert wurden, sind nur vor FROM
verfügbar und müssen danach neu deklariert werden, wenn du sie später brauchst.
Das passiert, weil jede FROM
Anweisung eine neue Bauphase mit einem eigenen Bereich startet. Dieses Verhalten ist mehr oder weniger obligatorisch, vor allem bei mehrstufigen Builds.
Erweiterte Deklarationstechniken
Lass uns eine komplette Flask "Hello World"-Anwendung erstellen, die Build-Args verwendet, um verschiedene Konfigurationen zu unterstützen:
> Lerne, wie du eine Anwendung mit Docker containerisieren kannst.
Erstelle zunächst eine einfache 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)
Erstelle in diesem Fall auch eine requirements.txt
Datei:
flask==3.1.0
Jetzt wollen wir ein Dockerfile erstellen, das Build-Args für eine flexible Konfiguration verwendet:
# 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"]
> Sieht das obige Dockerfilenfusing aus? Lerne Docker von Grund auf mit unserem Leitfaden.
Um dieses Image für die Entwicklung mit einer bestimmten Python-Version zu erstellen, kannst du Folgendes in deinem Terminal ausführen:
# Building for development with Python 3.11
docker build \
--build-arg PYTHON_VERSION=3.11 \
--build-arg ENVIRONMENT=development \
-t flaskapp:dev .
Abbildung 2 - Args in einer einfachen Python-Anwendung erstellen
Bei mehrstufigen Builds müssen die Build-Args besonders behandelt werden. Hier ist ein vollständiges Beispiel, das zeigt, wie du mit unserer Flask-App Argumente über mehrere Stufen weitergeben kannst:
# 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"]
Du kannst sie nun mit der jeweiligen Python-Version und -Umgebung bauen:
docker build \
--build-arg PYTHON_VERSION=3.12 \
--build-arg ENVIRONMENT=staging \
-t flaskapp:staging .
Abbildung 3 - Build-Args in mehrstufigen Builds
Kurz gesagt, dieser Ansatz ermöglicht es dir, eine einheitliche Konfiguration über alle Phasen deines Builds hinweg beizubehalten.
Vordefinierte Build-Argumente
Docker bietet mehrere vordefinierte Build-Args, die du verwenden kannst, ohne sie vorher zu deklarieren. Diese sind:
HTTP_PROXY
undHTTPS_PROXY
: Nützlich für Builds in Unternehmensumgebungen mit Proxy-Servern.FTP_PROXY
: Ähnlich wie HTTP-Proxys, aber für FTP-Verbindungen.NO_PROXY
: Gibt Hosts an, die den Proxy umgehen sollen.BUILD_DATE
undVCS_REF
: Wird oft für Bildmetadaten und die Versionskontrolle verwendet.
Diese vordefinierten Args sind praktisch, wenn du Images in Umgebungen mit bestimmten Netzwerkkonfigurationenerstellst . In einem Unternehmensnetzwerk mit strengen Proxy-Anforderungen kannst du zum Beispiel verwenden:
docker build --build-arg HTTP_PROXY=http://proxy.example.com:8080 .
Mit diesem Ansatz bleibt dein Dockerfile portabel und funktioniert auch in eingeschränkten Umgebungen.
Docker und Kubernetes beherrschen
Auswirkungen auf die Sicherheit und Risikominderung
Build-Argumente bieten zwar Flexibilität, aber sie bergen auch potenzielle Sicherheitsrisiken, die du kennen musst, um deine Docker-Images sicher zu halten.
Argument-Leck-Vektoren
Baustreitigkeiten sind nicht so privat, wie du vielleicht denkst. Die Werte von Build-Args können über verschiedene Vektoren durchsickern, die viele Entwickler übersehen. Erstens legt die Docker-Image-Historie alle deine Build-Args offen. Das bedeutet, dass jeder, der Zugriff auf dein Image hat, docker history
ausführen kann, um die Werte zu sehen, die du während der Build-Zeit verwendet hast, einschließlich potenziell sensibler Informationen wie API-Schlüssel oder Token.
docker history flaskapp:dev
Abbildung 4 - Docker Geschichte
Auch Zwischenschichten können Argumente für den Aufbau preisgeben. Auch wenn du einen mehrstufigen Build verwendest und den Layer mit den sensiblen Informationen nicht kopierst, bleiben die Build-Arg-Werte im Layer-Cache auf der Build-Maschine. Das bedeutet, dass jeder, der Zugriff auf den Docker-Daemon auf deinem Build-Server hat, diese Informationen möglicherweise auslesen kann.
CI/CD-Logs stellen ein weiteres großes Risiko dar. Die meisten CI/CD-Systeme protokollieren den gesamten Build-Befehl, einschließlich aller Build-Args, die auf der Kommandozeile übergeben werden.
Zum Beispiel wird dieser gesamte Befehl, einschließlich API_KEY
, in den CI/CD-Logs sichtbar sein:
docker build --build-arg API_KEY=secret123 -t myapp:latest .
Diese Logs sind oft für eine breitere Gruppe von Entwicklern zugänglich oder werden sogar in Systemen von Drittanbietern gespeichert, was die Angriffsfläche für sensible Werte vergrößert.
Sichere Alternativen
Für sensible Informationen solltest du die secrets-Funktion von Docker BuildKit anstelle von build args verwenden. Mit BuildKit kannst du Geheimnisse während des Build-Prozesses einbinden, ohne dass sie im endgültigen Image oder in der Historie bestehen bleiben.
Hier ist ein Beispiel für eine Dockerdatei, die Docker BuildKit-Geheimnisse verwendet:
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"]
Um dieses Bild mit einem Geheimnis zu erstellen, musst du zuerst die Datei api_key.txt
erstellen:
echo "my-secret-api-key" > api_key.txt
Und dann baue das Bild mit dem Geheimnis:
DOCKER_BUILDKIT=1 docker build \
--secret id=api_key,src=api_key.txt \
-t flaskapp:secure .
Abbildung 5 - Bilder mit BuildKit-Geheimnissen bauen
Für Konfigurationen, die zur Laufzeit verfügbar sein müssen, sind Umgebungsvariablen nach wie vor die beste Lösung. Sie können beim Starten eines Containers gesetzt werden, ohne dass sie in das Bild eingebacken werden:
# Set environment variables at runtime
docker run -e API_KEY=secret123 -p 5000:5000 flaskapp:latest
Um sensible Konfigurationen in der Produktion sicher zu handhaben, solltest du Container-Orchestrierungsplattformen wie Kubernetes verwenden, die sichere Methoden wie Secrets für die Verwaltung sensibler Informationen bieten. Auch Docker Swarm bietet mit seinem Secrets Management ähnliche Möglichkeiten.
> Docker ist nicht die einzige Plattform zur Containerisierung. Lies über Podman, um herauszufinden, welches Tool besser für dich geeignet ist.
Als Faustregel gilt: Verwende Build-Args für die Build-Time-Konfiguration, die nicht sensibel ist, verwende BuildKit-Geheimnisse für sensible Build-Time-Anforderungen und verwende Umgebungsvariablen oder Geheimnisse der Orchestrierungsplattform für die Laufzeitkonfiguration.
Integration mit Container-Ökosystemen
Nachdem die Grundlagen nun geklärt sind, wollen wir uns ansehen, wie man Build-Argumente in einem breiteren Docker-Ökosystem und modernen Build-Tools nutzen kann.
Docker Compose
Docker Compose macht es einfach, Build-Argumente für deine Multi-Container-Anwendungen zu definieren und gemeinsam zu nutzen.
Wenn du das nachvollziehen möchtest, findest du hier eine komplette Projektstruktur für zwei einfache Flask-Dienste:
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
Ich werde den Inhalt der Datei kurz nacheinander durchgehen:
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"
Kurz gesagt, ist dies eine sehr einfache Methode, um zwei Anwendungen in isolierten Umgebungen zu starten, beide zur gleichen Zeit und beide mit einem bestimmten Satz von Build-Args.
Du kannst diesen Befehl verwenden, um das Multi-Container-Setup auszuführen:
docker compose up --build
Abbildung 6 - Args mit Docker Compose bauen
Nach ein paar Sekunden siehst du, dass beide Dienste laufen:
Abbildung 7 - Args mit Docker Compose bauen (2)
Für so einfache Anwendungen wie diese beiden ist das ein ziemlich ausführliches Setup, aber du verstehst das große Ganze: Die Build-Argumente werden in der Compose-Datei festgelegt und in den einzelnen Dockerdateien referenziert.
Nebenbei bemerkt, kannst du auch Variablenwerte aus deiner Umgebung an die Build-Args übergeben, was für CI/CD-Pipelines praktisch ist:
services:
web:
build:
context: .
args:
- PYTHON_VERSION=${PYTHON_VERSION:-3.10}
Und um diese Werte beim Ausführen von docker-compose
zu überschreiben, kannst du Umgebungsvariablen verwenden:
PYTHON_VERSION=3.10 docker-compose up --build
Dieser Ansatz ermöglicht es dir, konsistente Builds in deinem Team aufrechtzuerhalten und trotzdem flexibel zu sein, wenn es nötig ist.
BuildKit-Funktionen
BuildKit, die moderne Build-Engine von Docker, optimiert deinen Build-Prozess mit Funktionen, die die Verwendung von Build-Args noch leistungsfähiger machen. Wenn du BuildKit aktivierst (indem du DOCKER_BUILDKIT=1
einstellst), schaltest du eine Reihe neuer Funktionen frei.
Der Inline-Cache verbessert die Build-Leistung, indem er den Build-Cache des Remote-Images nutzt. Mit dem Flag --cache-from
kannst du ein Quellbild angeben, das als Cache verwendet werden soll, und BuildKit wird die Ebenen dieses Bildes intelligent nutzen:
DOCKER_BUILDKIT=1 docker build \
--build-arg PYTHON_VERSION=3.10 \
--cache-from flaskapp:dev \
-t flaskapp:latest .
Eine weitere wertvolle Funktion von BuildKit sind deterministische Ausgaben, die sicherstellen, dass deine Builds reproduzierbar sind. Das ist wichtig, wenn du genau das gleiche Bild haben willst, egal wann und wo es gebaut wird:
# 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 \
.
Die geheime Redigierung von BuildKit in den Protokollen schützt sensible Informationen während der Builds.
Im Gegensatz zu normalen Build-Args, die in den Build-Logs erscheinen, verbirgt BuildKit automatisch die Werte von 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 deinem Dockerfile greifst du auf dieses Geheimnis mit zu:
RUN --mount=type=secret,id=api_key \
cat /run/secrets/api_key > /app/config/api_key.txt
Diese BuildKit-Funktionen arbeiten mit Build-Args zusammen, um ein sichereres, effizienteres und reproduzierbares Build-System zu schaffen, das sich an praktisch jeden Containerisierungs-Workflow anpassen kann.
Best Practices für die Einführung in Unternehmen
Die Implementierung von Docker-Build-Argumenten in großen Teams erfordert standardisierte Ansätze, zumindest wenn du die Verwirrung minimieren und die Sicherheits- und Leistungsvorteile maximieren willst.
Wenn du Build-Args in Unternehmensumgebungen einführst, solltest du mit der richtigen Validierung der Argumente beginnen.
Gib immer sinnvolle Standardwerte für jedes Build-Argument an, um sicherzustellen, dass Builds nicht unerwartet fehlschlagen, wenn die Argumente nicht übergeben werden. Du solltest auch Validierungsprüfungen in dein Dockerfile einbauen, um sicherzustellen, dass kritische Build-Args deinen Anforderungen entsprechen.
Hier ist ein Beispiel, das die Python-Version überprüft:
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
Die Optimierung des Layer-Cachings ist entscheidend für die Reduzierung der Build-Zeiten in CI/CD-Pipelines.
Ordne deine Dockerfile-Anweisungen so an, dass du die Cache-Treffer maximierst, indem du selten wechselnde Inhalte (wie die Installation von Abhängigkeiten) vor häufig wechselnden Inhalten (wie dem Anwendungscode) platzierst.
Wenn du Build-Args verwendest, die sich häufig ändern können, platziere sie nach stabilen Operationen, damit nicht der gesamte Cache ungültig wird:
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
Die Verwaltung von Metadaten durch Build-Args verbessert die Rückverfolgbarkeit und die Einhaltung von Vorschriften. Verwende Build-Args, um Metadaten zur Build-Zeit als Labels einzufügen:
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}"
Diese standardisierten Labels folgen der Spezifikation der Open Container Initiative (OCI), was bedeutet, dass deine Images mit verschiedenen Container-Management-Tools kompatibel sind.
Die Dokumentation wird oft übersehen, aber sie ist entscheidend für die Akzeptanz in Unternehmen.
Erstelle einen übersichtlichen README
Abschnitt, der alle verfügbaren Build-Args, ihren Zweck, ihre Standardwerte und Anwendungsbeispiele dokumentiert. Gib an, welche Build-Argumente erforderlich und welche optional sind, und dokumentiere alle Wechselwirkungen zwischen den verschiedenen Argumenten. Erwäge, diese Informationen auch als Kommentare in die Konfigurationsdateien deiner CI/CD-Pipeline aufzunehmen, damit die Entwickler wissen, welche Werte sie angeben müssen:
# 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} .
Für eine wirklich unternehmenstaugliche Einführung solltest du ein Schema für Build-Argumente einführen, das versioniert und validiert werden kann. Mit diesem Ansatz kannst du deine Build-Konfiguration im Laufe der Zeit weiterentwickeln und gleichzeitig die Abwärtskompatibilität wahren.
Vergleichende Analyse: Build Args vs. Umgebungsvariablen
Wenn du sichere und flexible Docker-Images erstellen willst, die den Best Practices folgen, musst du wissen, wann du Build-Argumente und wann du Umgebungsvariablen verwenden solltest.
Hier ist eine Tabelle, die du jederzeit nachschlagen kannst:
Feature |
Argumente aufbauen |
Umgebungsvariablen |
Verfügbarkeit |
Nur während der Imageerstellung verfügbar |
Verfügbar sowohl während des Builds als auch während der Container-Laufzeit |
Persistenz |
Wird im endgültigen Bild nicht beibehalten (es sei denn, es wird explizit in |
Bleibt im Image erhalten und ist für laufende Container verfügbar |
Sicherheit |
Sichtbar im Bildverlauf mit Docker History |
Nicht sichtbar in der Bildgeschichte, aber zugänglich für Prozesse innerhalb des Containers |
Verwendung |
Ideal für die Konfiguration zur Build-Zeit wie Versionen, Build-Pfade, Compiler-Flags |
Ideal für die Laufzeitkonfiguration wie Verbindungsstrings, Funktionsflags, Loglevel |
Erklärung |
Definiert mit der Anweisung |
Definiert mit der Anweisung |
Standardwerte |
Kann Standardwerte bereitstellen: |
Kann Standardwerte bereitstellen: |
Umfang |
Wird für jede Bauphase festgelegt und muss nach jeder Bauphase neu deklariert werden. |
Verfügbar in allen Baustufen und vererbt an untergeordnete Bilder |
Überschreibungsmethode |
|
|
Der entscheidende Unterschiedliegt in ihrem Zeitpunkt und ihrem Zweck. Build-Args konfigurieren den Build-Prozess selbst, während Umgebungsvariablen die laufende Anwendung konfigurieren. Du würdest zum Beispiel ein Build-Arg verwenden, um das zu verwendende Basis-Image auszuwählen (ARG PYTHON_VERSION=3.10
), aber du würdest eine Umgebungsvariable verwenden, um deiner Anwendung mitzuteilen, auf welchem Port sie lauschen soll (ENV PORT=8080
).
Aus einer Sicherheitsperspektive stellen Build-Args ein höheres Risiko für sensible Informationen dar, da sie in der Image History verbleiben.
Betrachte diesen Arbeitsablauf für die Handhabung verschiedener Arten von Konfigurationen:
# 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 der Praxis ist es üblich, ausgewählte Build-Args in Umgebungsvariablen umzuwandeln, wenn sie zur Laufzeit verfügbar sein sollen:
ARG APP_VERSION=1.0.0
# Make the version available at runtime
ENV APP_VERSION=${APP_VERSION}
Bei Unternehmensanwendungen ermöglicht die Trennung, dass verschiedene Teams unterschiedliche Aspekte des Lebenszyklus der Anwendung verwalten. DevOps-Teams können die Build-Args für die Image-Erstellung ändern, während die Betreiber die Umgebungsvariablen während der Bereitstellung anpassen können, ohne die Images neu zu erstellen.
Zusammenfassung der Docker Build Args
Docker-Build-Args sind nicht nur ein weiteres technisches Feature - sie sind dein wichtigstes Werkzeug, um Images zu erstellen, die in deinem Team und deinen Umgebungen einheitlich funktionieren.
Ich habe dir gezeigt, wie du sie in einfachen Python-Projekten einsetzen kannst, ohne dass deine sensiblen Daten in Gefahr geraten. Du hast auch gesehen, wie man Build-Args in Tools wie Docker Compose integriert.
Betrachte Build-Args als Grundlage für eine flexible Containerisierungsstrategie. Fang klein an, indem du deine Python-Version in deinem nächsten Projekt parametrisierst. Wenn du dich damit wohlfühlst, kannst du versuchen, bedingte Logik für verschiedene Umgebungen hinzuzufügen. Im Handumdrehen erstellst du ausgefeilte mehrstufige Builds, die dein Team anpassen kann, ohne die Dockerdatei zu verändern.
Bist du bereit, tiefer einzutauchen? Diese Kurse von DataCamp sind die beste Anlaufstelle für dich:
Docker und Kubernetes beherrschen
FAQs
Was sind Docker-Build-Argumente?
Docker-Build-Argumente (build args) sind Variablen, die du dem Docker-Build-Prozess übergibst und die nur während der Image-Erstellung verfügbar sind. So kannst du dein Dockerfile anpassen, ohne es zu verändern, und deine Container-Builds flexibler und wiederverwendbar machen. Betrachte sie als Parameter, die du jedes Mal, wenn du ein Bild erstellst, anpassen kannst, um mit verschiedenen Umgebungen oder Konfigurationen umzugehen.
Wie unterscheiden sich die Build-Args von den Umgebungsvariablen in Docker?
Build-Args existieren nur während der Erstellung des Images, während die Umgebungsvariablen im laufenden Container bestehen bleiben. Build-Args werden mit der Anweisung ARG
definiert und beim Bauen über das Flag --build-arg
übergeben. Damit sind sie ideal für Dinge wie die Auswahl von Basis-Images oder die Festlegung von Build-Time-Konfigurationen. Umgebungsvariablen, die mit ENV
definiert werden, sind für die Laufzeitkonfiguration gedacht, die deine Anwendung während der Ausführung benötigt.
Welche Sicherheitsbedenken sollte ich bei der Verwendung von Docker-Build-Args beachten?
Build-Args sind nicht so privat, wie viele Entwicklerinnen und Entwickler annehmen - ihre Werte sind im Imageverlauf und in den CI/CD-Logs sichtbar. Verwende niemals Build-Args für sensible Informationen wie API-Schlüssel oder Passwörter, da jeder, der Zugriff auf dein Bild hat, diese Werte sehen kann. Für sensible Daten solltest du stattdessen Docker BuildKit-Geheimnisse verwenden, die nicht im endgültigen Image oder im Verlauf verbleiben.
Wie kann ich Build-Args durch CI/CD-Pipelines wie GitHub Actions leiten?
Die meisten CI/CD-Plattformen unterstützen Docker-Build-Args über ihre Konfigurationsdateien. In GitHub Actions kannst du Build-Args in deiner Workflow-YAML mit dem Parameter build-args unter der docker/build-push-action übergeben. Je nach deinen Sicherheitsanforderungen kannst du auf Umgebungsvariablen, Repository Secrets oder fest kodierte Werte verweisen. So kannst du Builds mit unterschiedlichen Konfigurationen auf Basis von Branch, Umgebung oder anderen CI-Variablen automatisieren.
Gibt es eine Grenze für die Anzahl der Build-Args, die ich in einem Dockerfile verwenden kann?
Es gibt keine feste technische Grenze für die Anzahl der Build-Args, aber zu viele können dein Dockerfile schwer verständlich und wartungsintensiv machen. Bei Data-Science-Projekten konzentrierst du dich auf die Parametrisierung kritischer Variablen wie die Python-Version, die Wahl des Frameworks oder die Konfiguration der Datensätze. Wenn du mehr als 8-10 Build-Args hast, solltest du in Erwägung ziehen, dein Dockerfile in kleinere, gezieltere Dateien aufzuteilen oder Docker Compose zu verwenden, um die Komplexität zu bewältigen.
Lerne mehr über Docker mit diesen Kursen!
Kurs
Introduction to Docker
Kurs
Intermediate Docker
Der Blog
Die 50 besten AWS-Interview-Fragen und Antworten für 2025

Der Blog
Lehrer/innen und Schüler/innen erhalten das Premium DataCamp kostenlos für ihre gesamte akademische Laufbahn
Der Blog
2022-2023 DataCamp Classrooms Jahresbericht
Der Blog
Q2 2023 DataCamp Donates Digest
Der Blog
Die 20 besten Snowflake-Interview-Fragen für alle Niveaus

Nisha Arya Ahmed
15 Min.
Der Blog
Top 30 Generative KI Interview Fragen und Antworten für 2024

Hesam Sheikh Hassani
15 Min.