Dockerfile: Aufbau und Funktion erklärt

Autor: Veröffentlicht

Kurz gesagt: Ein Dockerfile ist eine Textdatei mit Anweisungen, nach denen Docker ein Anwendungsimage baut – ein Paket mit dem Code der Anwendung, den benötigten Werkzeugen und Einstellungen. Aus einem solchen Image lassen sich Container starten, also isolierte Prozesse mit einer vorbereiteten Umgebung. Ein Dockerfile beschreibt somit, wie eine Anwendung für den Start vorbereitet wird, ist aber selbst kein laufender Container.

Dockerfile, Image und Container – drei verschiedene Dinge

Ein Dockerfile lässt sich mit einem Rezept vergleichen, ein Image mit einem danach zusammengestellten Paket und ein Container mit einer laufenden Instanz dieses Pakets. Aus einem Image können mehrere Container entstehen, etwa mehrere Instanzen derselben Anwendung.

Im Dockerfile legst du unter anderem die Basisumgebung, die zu kopierenden Dateien, die zu installierenden Abhängigkeiten und den standardmäßigen Startbefehl fest. So musst du nicht jeden Server manuell nach einer separaten Anleitung einrichten. Wenn sich der Code oder die Abhängigkeiten ändern, baust du üblicherweise ein neues Image.

Ein Container ist keine vollständige virtuelle Maschine: Er nutzt den Betriebssystemkernel der Umgebung, in der die Container-Engine läuft. Ein Image hilft, die Anwendungsumgebung zu vereinheitlichen, beseitigt aber nicht alle Unterschiede zwischen Rechnern. Beispielsweise spielen die Prozessorarchitektur, die Netzwerkkonfiguration und der Zugriff auf Dateien weiterhin eine Rolle.

Welche Anweisungen enthält ein Dockerfile?

Die Datei heißt üblicherweise Dockerfile, ohne Dateiendung. Jede Anweisung beschreibt einen bestimmten Build-Schritt oder eine Einstellung des Images. Am häufigsten begegnen dir:

Entscheidend ist der Unterschied zwischen RUN und CMD. RUN wird beim Erstellen des Images ausgeführt, CMD dagegen erst beim Start des Containers. Die Installation von Abhängigkeiten gehört üblicherweise zu RUN, der Start des Servers zu CMD.

Außerdem gibt es ENTRYPOINT, das das Hauptprogramm des Containers festlegt. Es lässt sich mit CMD kombinieren, um diesem Programm Standardargumente zu übergeben. Für das erste einfache Beispiel genügt CMD allein.

Einfaches Beispiel: eine HTML-Seite im Container

Angenommen, du möchtest eine einfache Seite lokal betreiben, ohne Python auf deinem Rechner zu installieren. Du brauchst eine funktionierende Installation von Docker und ein Verzeichnis mit zwei Dateien: index.html und Dockerfile.

Füge in die Datei index.html Folgendes ein:

<!doctype html>
<html lang="de">
<meta charset="utf-8">
<title>Docker-Beispiel</title>
<h1>Die Seite läuft im Container</h1>
</html>

Die Datei Dockerfile kann so aussehen:

FROM python:3.13-slim
WORKDIR /app
COPY index.html .
EXPOSE 8000
CMD ["python", "-m", "http.server", "8000", "--bind", "0.0.0.0"]

Docker verwendet ein Image mit Python, legt /app als Arbeitsverzeichnis fest und kopiert die Seite dorthin. Beim Start des Containers wird ein einfacher HTTP-Server gestartet. Die Adresse 0.0.0.0 bedeutet, dass der Server auf allen Netzwerkschnittstellen des Containers lauscht. Dadurch ist er über den veröffentlichten Port erreichbar.

Führe im Terminal im Verzeichnis mit diesen Dateien Folgendes aus:

docker build -t meine-seite .
docker run --rm -p 127.0.0.1:8080:8000 meine-seite

Der erste Befehl baut das Image und gibt ihm den Namen meine-seite. Der Punkt legt das aktuelle Verzeichnis als Build-Kontext fest, also als die Sammlung von Dateien, die dem Build-Prozess zur Verfügung stehen. Der zweite Befehl startet einen Container und verbindet den lokalen Port 8080 mit dem Port 8000 des Containers.

Öffne http://localhost:8080 im Browser. Die Bindung des Ports an 127.0.0.1 beschränkt den Zugriff auf den lokalen Rechner. Mit Ctrl+C stoppst du den Server; die Option --rm entfernt den beendeten Container. Dies ist ein Lernbeispiel, keine Konfiguration für einen Produktionsserver.

Was beeinflusst Geschwindigkeit und Sicherheit des Builds?

Dank eines Zwischenspeichers, des sogenannten Cache, kann Docker die Ergebnisse früherer Schritte wiederverwenden. Wenn sich Dateien ändern, die eine Anweisung verwendet, müssen dieser Schritt und die folgenden davon abhängigen Schritte möglicherweise erneut ausgeführt werden. Bei Anwendungen mit Bibliotheken wird deshalb häufig zuerst die Datei mit den Abhängigkeiten kopiert und die Paketinstallation ausgeführt. Erst danach wird der Code kopiert, der sich häufiger ändert.

Die Datei .dockerignore schließt unnötige Dateien aus dem Build-Kontext aus. Typischerweise betrifft das das Verzeichnis .git, lokale Umgebungen, Logs und Dateien mit Geheimnissen. Das verringert die übertragene Datenmenge und das Risiko, versehentlich vertrauliche Inhalte einzuschließen.

Speichere Passwörter und Tokens weder im Dockerfile noch kopiere sie in das Image. Ein Geheimnis in einem späteren Schritt zu löschen, garantiert nicht, dass es auch aus früheren Image-Schichten entfernt wird. Übergib Geheimnisse, die beim Build benötigt werden, über die Secret-Mechanismen von BuildKit. Daten, die die laufende Anwendung benötigt, stellst du über eine entsprechende Konfiguration der Laufzeitumgebung bereit.

Für den Produktivbetrieb solltest du erwägen, die Anwendung als Benutzer ohne Administratorrechte auszuführen. Behalte auch die Version des Basisimages im Blick: Ein Tag kann mit der Zeit auf ein verändertes Image verweisen, während ein Digest einen bestimmten Inhalt eindeutig identifiziert. Prüfe die verfügbaren Versionen und das Vorgehen bei Updates in der offiziellen Dokumentation des gewählten Images.

Wann brauchst du ein Dockerfile, wann Compose?

Ein Dockerfile beantwortet die Frage: „Wie wird das Image gebaut?“ Docker Compose dient dazu, mehrere Dienste – etwa eine Anwendung, eine Datenbank und einen Cache – samt ihren Netzwerken, Ports und Volumes zu beschreiben und zu starten. Ein Volume ist ein Mechanismus zur Speicherung von Daten unabhängig von der Lebensdauer eines einzelnen Containers.

Diese Werkzeuge können zusammenarbeiten: Compose kann ein Image anhand eines Dockerfile bauen und es anschließend neben einem fertigen Datenbankimage starten. Wenn du ausschließlich fertige Images verwendest, brauchst du nicht immer ein eigenes Dockerfile.

Beginne damit, ein einfaches Image zu bauen und zu starten. Ersetze anschließend die Beispielseite durch deine eigene Anwendung, lege ihre Abhängigkeiten ausdrücklich fest und prüfe, welche Dateien tatsächlich in das Image gehören.

Siehe auch: Was ist eine API?

Lesen Sie auch

Wie PHP-FPM PHP-Anfragen verarbeitet, sich vom Webserver unterscheidet und wie du Prozesse an Last und Hosting-Ressourcen anpasst.
BIND ist offene DNS-Serversoftware. Erfahre, welche Aufgaben sie übernimmt und wann sich der Betrieb eines eigenen Servers lohnt.
Was Polens REGON-Register und seine Kennnummer bedeuten, wie sie sich von NIP und KRS unterscheiden und wie Sie Unternehmensdaten prüfen.