Dockerfile mit Ubuntu: Schritt-für-Schritt-Anleitung für Entwickler

目次

1. Einleitung

Was sind Docker und Dockerfile?

In den letzten Jahren hat sich Docker rasant als effiziente Lösung zur Einrichtung von Entwicklungsumgebungen und für das Deployment von Anwendungen etabliert. Docker verpackt eine Anwendung und deren Abhängigkeiten als sogenannten „Container“, der überall in der gleichen Umgebung ausgeführt werden kann.

Für den Aufbau eines solchen Docker-Containers wird eine sogenannte Dockerfile benötigt. Eine Dockerfile ist eine Textdatei, in der das Basis-Betriebssystem, die zu installierende Software und Umgebungsvariablen definiert werden. Entwickler können mit dieser Datei automatisiert individuell angepasste Umgebungen erstellen.

Warum als Basis Ubuntu wählen?

Bei der Erstellung einer Dockerfile muss zuerst das Basis-OS-Image angegeben werden. Besonders beliebt ist dabei Ubuntu. Ubuntu ist eine auf Debian basierende Linux-Distribution, die sich durch Benutzerfreundlichkeit und eine große Auswahl an Paketen für flexible Umgebungen auszeichnet.

Ein auf Ubuntu basierendes Dockerfile bietet folgende Vorteile:

  • Zahlreiche offizielle und Community-Dokumentationen erleichtern das Lernen
  • Viele Pakete und Tools lassen sich unkompliziert über APT installieren
  • Offizielle, schlanke Minimal-Images (ubuntu:20.04, ubuntu:24.04 etc.) sind verfügbar

Ziel & Zielgruppe dieses Artikels

In diesem Artikel erklären wir unter dem Stichwort „Dockerfile Ubuntu“, wie man ein Ubuntu-basiertes Dockerfile auch als Einsteiger einfach erstellt.

Konkret behandeln wir den grundlegenden Aufbau einer Dockerfile, die praktische Umsetzung für Ubuntu-Umgebungen, Beispiele für die Integration von Python-Anwendungen sowie häufige Fehler und deren Lösungen.

Dieser Beitrag ist besonders geeignet für:

  • Alle, die zum ersten Mal eine Umgebung mit Dockerfile aufbauen möchten
  • Entwickler, die eine reproduzierbare Entwicklungsumgebung mit Ubuntu anlegen wollen
  • Leser, die auch Problemlösungen und Troubleshooting kennenlernen möchten

2. Grundstruktur einer Dockerfile

Was ist eine Dockerfile? Rolle und Nutzen

Eine Dockerfile ist wie ein Rezept für das Erstellen eines Docker-Images. Konkret wird darin festgelegt, welches Basis-OS verwendet wird, welche Software installiert und welche Konfigurationen vorgenommen werden.

Mit dem docker build-Befehl kann anhand der Dockerfile schnell und zuverlässig eine Entwicklungs- oder Ausführungsumgebung gebaut werden.

Vorteile einer Dockerfile:

  • Automatisierung der Umgebungseinrichtung (keine manuellen Wiederholungen nötig)
  • Gleiche Umgebung für alle Teammitglieder – keine Abweichungen
  • Leicht in CI/CD-Pipelines integrierbar

Wichtige Befehle (Direktiven) in einer Dockerfile

Folgende Direktiven werden in einer Dockerfile häufig verwendet. Sie bilden die Basis für Ubuntu-Dockerfiles:

BefehlBeschreibung
FROMDefiniert das Basis-Image, z. B.: FROM ubuntu:24.04
RUNFührt Shell-Kommandos aus, etwa zur Paketinstallation
COPYKopiert lokale Dateien ins Image
ADDÄhnlich wie COPY, kann aber auch aus URLs laden und Archive entpacken
WORKDIRSetzt das Arbeitsverzeichnis
ENVSetzt Umgebungsvariablen
CMDDefiniert den beim Start auszuführenden Befehl (überschreibbar)
ENTRYPOINTLegt einen auszuführenden Befehl fest, der immer gestartet wird

Minimalbeispiel: Dockerfile auf Ubuntu-Basis

Ein einfaches Beispiel für ein Ubuntu-basiertes Dockerfile:

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y \
    curl \
    vim

CMD ["/bin/bash"]

Dieses Dockerfile verwendet Ubuntu 24.04 als Basis, installiert die Tools curl und vim und startet abschließend die bash-Shell.

Hinweise zur Ubuntu-Tag-Wahl

Ubuntu-Images sind im offiziellen Docker Hub Repository verfügbar. Mit ubuntu:latest erhält man immer die neueste Version, es wird jedoch empfohlen, die Version explizit anzugeben.

Beispiele:

  • ubuntu:22.04 (LTS: Long Term Support, Stabilität)
  • ubuntu:24.04 (neustes LTS, aktuelle Features)

Je nach Einsatzzweck sollte man Stabilität oder Aktualität priorisieren.

3. Praxis: Erstellung eines Ubuntu-Dockerfiles

Wichtige Pakete in einer Ubuntu-Umgebung installieren

Beim Aufbau einer Ubuntu-Umgebung per Dockerfile werden häufig zusätzliche Pakete benötigt. Typische Utilities für die Entwicklungsumgebung sind zum Beispiel:

  • curl: Download von Dateien, API-Tests
  • vim: Texteditor
  • git: Versionsverwaltung
  • build-essential: Tools zum Bauen von C/C++

Die Installation erfolgt mit dem RUN-Befehl:

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y \
    curl \
    vim \
    git \
    build-essential

Das vorgelagerte apt-get update aktualisiert die Paketlisten.

Nicht-interaktive Installation

Da apt-get install manchmal Benutzereingaben benötigt, empfiehlt sich für den automatisierten Docker-Build der nicht-interaktive Modus:

ENV DEBIAN_FRONTEND=noninteractive

Damit werden z. B. Rückfragen zur Region oder Sprache übersprungen und die Installation läuft automatisch durch.

Image-Verkleinerung durch Cache-Löschung

APT speichert temporäre Dateien im Image. Durch das Löschen des Caches verringert sich die Image-Größe:

RUN apt-get update && apt-get install -y \
    curl \
    vim \
    && rm -rf /var/lib/apt/lists/*

Zudem sollte man möglichst viele Kommandos in einer RUN-Zeile bündeln, um die Layer-Anzahl zu minimieren.

Best Practices für Dockerfiles

Empfohlene Best Practices für produktionsreife Dockerfiles:

  • RUN-Befehle bündeln, um Layer zu reduzieren
  • Versionen und Einstellungen mit ENV deklarieren
  • Zweck der Befehle mit Kommentaren erläutern
  • Unnötige Dateien vermeiden, rm und --no-install-recommends verwenden

Beispiel:

RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    git \
    && rm -rf /var/lib/apt/lists/*

So werden Dockerfiles wartbarer und Images schlanker.

4. Docker-Image bauen und überprüfen

Docker-Image aus Dockerfile bauen

Nach dem Schreiben der Dockerfile erfolgt der Build mit folgendem Befehl im entsprechenden Verzeichnis:

docker build -t my-ubuntu-image .
  • -t legt den Namen (Tag) des Images fest, hier z. B. my-ubuntu-image.
  • . steht für das aktuelle Verzeichnis mit der Dockerfile.

Docker liest die Befehle sequentiell aus und erstellt ein neues Image.

Erstellte Docker-Images überprüfen

Mit folgendem Befehl lässt sich die Übersicht anzeigen:

docker images

Beispielausgabe:

REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
my-ubuntu-image   latest    abcd1234abcd   vor 5 Minuten    189MB

So sieht man, dass das Image erfolgreich erstellt wurde.

Container starten und Funktion prüfen

Mit folgendem Befehl kann das Image als Container gestartet und getestet werden:

docker run -it my-ubuntu-image
  • -it startet ein interaktives Terminal.
  • Bei Erfolg erscheint die Bash-Shell der Ubuntu-Umgebung.

Testen Sie installierte Tools im Container z. B. so:

curl --version
vim --version

Wenn alles wie erwartet funktioniert, ist das Dockerfile korrekt.

Nicht mehr benötigte Images und Container bereinigen

Um Speicherplatz zu sparen und Probleme zu vermeiden, empfiehlt sich regelmäßiges Aufräumen mit folgenden Befehlen:

  • Gestoppte Container entfernen:
docker container prune
  • Unbenutzte Images löschen:
docker image prune
  • Alles Unbenutzte löschen (Vorsicht!):
docker system prune

Dies spart Speicher und verhindert Konflikte.

5. Erweiterung: Python-Umgebung aufbauen

Python in Ubuntu-Dockerfiles nutzen

Mit einer Dockerfile lässt sich eine Python-Entwicklungsumgebung flexibel aufbauen. Auch wenn Ubuntu oft Python vorinstalliert hat, empfiehlt sich aus Gründen der Versionskontrolle eine explizite Installation.

Python-Installation per APT

Der einfachste Weg ist die Installation über die Paketverwaltung:

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*

Damit steht ein aktuelles, stabiles Python samt pip zur Verfügung. Zusätzliche Pakete können mit pip installiert werden.

pyenv zur Python-Versionverwaltung nutzen

Für spezielle Python-Versionen oder Multi-Versionen empfiehlt sich pyenv:

Beispiel für Python 3.11.6 Installation via pyenv im Dockerfile:

FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
    git \
    curl \
    make \
    build-essential \
    libssl-dev \
    zlib1g-dev \
    libbz2-dev \
    libreadline-dev \
    libsqlite3-dev \
    wget \
    llvm \
    libncurses5-dev \
    libncursesw5-dev \
    xz-utils \
    tk-dev \
    libffi-dev \
    liblzma-dev \
    && rm -rf /var/lib/apt/lists/*

# pyenv installieren
RUN git clone https://github.com/pyenv/pyenv.git ~/.pyenv

ENV PYENV_ROOT="$HOME/.pyenv"
ENV PATH="$PYENV_ROOT/bin:$PATH"

RUN echo 'eval "$(pyenv init --path)"' >> ~/.bashrc

# Gewünschte Python-Version installieren
RUN pyenv install 3.11.6 && pyenv global 3.11.6

Damit können verschiedene Python-Versionen parallel gemanagt werden.

Python-Pakete via requirements.txt verwalten

Für Projekte mit mehreren Abhängigkeiten empfiehlt sich ein requirements.txt:

flask==2.3.2
requests>=2.25.1
pandas

Dockerfile-Auszug:

COPY requirements.txt /app/requirements.txt
WORKDIR /app

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

So wird die Paketinstallation reproduzierbar und komfortabel.

Best Practices für Python mit Docker

  • Virtuelle Umgebungen (virtualenv oder venv) nutzen zur Vermeidung von Abhängigkeitskonflikten
  • Mit --no-cache-dir wird das Image kleiner
  • Vor der Paketinstallation pip install --upgrade pip verwenden, um Fehler zu vermeiden

6. Häufige Probleme & Lösungen

Fehler: Berechtigungen (Permission denied)

Beispiel:

Permission denied

Passiert, wenn kopierte Dateien keine Ausführungsrechte haben oder Nutzer falsch gesetzt sind.

Lösung:

  • Dateien ausführbar machen:
  RUN chmod +x script.sh
  • Ggf. Nutzer/Gruppe anpassen:
  RUN chown root:root /pfad/zu/datei

Paket nicht gefunden oder Installation schlägt fehl

Beispiel:

E: Unable to locate package xxx

Oft, wenn apt-get update nicht ausgeführt oder Paketname falsch geschrieben wurde.

Lösung:

  • apt-get update immer vor install verwenden:
  RUN apt-get update && apt-get install -y curl
  • Paketnamen auf Korrektheit prüfen

Netzwerkprobleme

Beispiel:

Temporary failure resolving 'deb.debian.org'

Typisch bei Problemen mit der DNS-Auflösung während des Builds.

Lösung:

  • Docker-Daemon neu starten:
  sudo systemctl restart docker
  • DNS-Einstellungen in /etc/docker/daemon.json anpassen:
  {
    "dns": ["8.8.8.8", "8.8.4.4"]
  }

Veralteter Build durch Cache

Docker verwendet Caching für Layer, dadurch werden Änderungen manchmal nicht übernommen.

Lösung:

  • Build ohne Cache:
  docker build --no-cache -t my-image .

Startbefehl im Container läuft nicht / beendet sofort

Ursachen:

  • CMD oder ENTRYPOINT falsch oder fehlerhaft
  • Bei CMD ["/bin/bash"] ohne -it schließt der Container sofort

Lösung:

  • Container zum Debuggen interaktiv starten:
  docker run -it my-image /bin/bash
  • Unterschiede zwischen CMD und ENTRYPOINT beachten

Mit Erfahrung werden Fehler schneller analysiert. Die Fehlermeldung gibt meist Hinweise auf das Problem.

7. Fazit

Wichtige Punkte für Ubuntu-Dockerfiles

In diesem Beitrag haben wir Schritt für Schritt die Erstellung von Ubuntu-basierten Dockerfiles erläutert. Die wichtigsten Takeaways:

  • Grundstruktur von Dockerfiles verstehen:
    FROM, RUN, CMD, ENV u. a. sorgen für automatisierte Umgebungserstellung.
  • Ubuntu als stabiles, flexibles Basis-Image
    Mit umfangreichen Paketen, großer Nutzerbasis und LTS-Versionen ideal als Entwicklungsgrundlage.
  • Effizientes Paketmanagement:
    Tools und Bibliotheken per apt-get installieren, Cache löschen, nicht-interaktive Modi nutzen.
  • Reale Entwicklungsumgebungen, z. B. für Python, lassen sich via pyenv, pip und requirements.txt exakt abbilden.
  • Problemlösungs-Kompetenz ist zentral
    Wer Fehlerursachen versteht, steigert die Entwicklungs-Effizienz deutlich.

Nächste Schritte beim Lernen von Dockerfiles

Mit Dockerfiles lassen sich nicht nur Entwicklungs-, sondern auch Test- und Produktionsumgebungen flexibel verwalten. Weitere empfohlene Themen:

  • Mehrere Container mit Docker Compose orchestrieren
  • Anbindung an CI/CD-Tools (z. B. GitHub Actions, GitLab CI)
  • Container-Orchestrierung mit Kubernetes u. a.

Offizielle Dokumentation & Links

8. FAQ (Häufig gestellte Fragen)

Q1. Welche Ubuntu-Version sollte ich im Dockerfile wählen?

A1. Für Stabilität empfiehlt sich ein LTS (Long Term Support)-Release wie ubuntu:22.04 oder ubuntu:20.04. Diese erhalten 5 Jahre Support und sind in der Entwicklung weit verbreitet.

Für neueste Pakete und Features kann ubuntu:24.04 gewählt werden, sollte aber getestet werden.

Q2. Warum erhalte ich bei apt-get install die Meldung „Paket nicht gefunden“?

A2. Der häufigste Grund: apt-get update wurde nicht vorher ausgeführt. Ohne aktuelle Paketlisten kann das gewünschte Paket nicht gefunden werden.

Richtiges Beispiel:

RUN apt-get update && apt-get install -y curl

Auch Tippfehler im Paketnamen oder veraltete Namen (z. B. python statt python3) prüfen.

Q3. Wie setze ich Umgebungsvariablen in einer Dockerfile?

A3. Mit dem Befehl ENV, der für Build- und Laufzeit gilt.

Beispiel:

ENV DEBIAN_FRONTEND=noninteractive

Oft genutzt, um Installationsdialoge zu unterdrücken. Auch für App-Settings, API-Keys usw. einsetzbar.

Q4. Was ist der Unterschied zwischen CMD und ENTRYPOINT?

A4. Beide definieren Startbefehle für den Container, verhalten sich aber unterschiedlich:

OptionCMDENTRYPOINT
ÜberschreibbarkeitMit docker run überschreibbarWird immer ausgeführt, weitere Argumente werden übergeben
ZweckStandardbefehl definierenZwingend auszuführender Befehl

Beispiel:

CMD ["python3", "app.py"]
# vs
ENTRYPOINT ["python3"]
CMD ["app.py"]

Im zweiten Fall kann man z. B. docker run my-image another_script.py ausführen.

Q5. Warum werden Änderungen an der Dockerfile nicht übernommen?

A5. Docker verwendet beim Build ein Caching, wodurch kleinere Änderungen evtl. nicht übernommen werden.

Lösung:

docker build --no-cache -t my-image .

Damit werden alle Layer neu gebaut und alle Änderungen angewandt.