5 Docker-Best Practices für schnellere Builds und kleinere Images
Bild vom Autor

# Einführung

Sie haben Ihre Docker-Datei geschrieben, Ihr Picture erstellt und alles funktioniert. Aber dann fällt Ihnen auf, dass das Picture mehr als ein Gigabyte groß ist, der Neuaufbau selbst bei der kleinsten Änderung Minuten dauert und sich jedes Drücken oder Ziehen quälend langsam anfühlt.

Das ist nicht ungewöhnlich. Dies sind die Standardergebnisse, wenn Sie Docker-Dateien schreiben, ohne über die Auswahl des Foundation-Pictures, den Construct-Kontext und das Caching nachzudenken. Um das Drawback zu beheben, ist keine komplette Überholung erforderlich. Ein paar gezielte Änderungen können Ihr Bild um 60–80 % verkleinern und die meisten Wiederherstellungen von Minuten in Sekunden verwandeln.

In diesem Artikel gehen wir fünf praktische Techniken durch, damit Sie lernen, wie Sie Ihre Docker-Pictures kleiner, schneller und effizienter machen.

# Voraussetzungen

Um mitzumachen, benötigen Sie:

  • Docker installiert
  • Grundlegende Vertrautheit mit Dockerfiles und die docker construct Befehl
  • Ein Python-Projekt mit a necessities.txt Datei (die Beispiele verwenden Python, aber die Prinzipien gelten für jede Sprache)

# Auswahl von Slim- oder Alpine-Basisbildern

Jede Docker-Datei beginnt mit a FROM Anweisung, die ein Basisbild auswählt. Dieses Basisbild ist die Grundlage Ihrer App und seine Größe wird zu Ihrer Mindestbildgröße, bevor Sie eine einzelne Zeile Ihres eigenen Codes hinzugefügt haben.

Zum Beispiel der Beamte python:3.11 Das Picture ist ein vollständiges Debian-basiertes Picture, das mit Compilern, Dienstprogrammen und Paketen geladen ist, die die meisten Anwendungen nie verwenden.

# Full picture — every part included
FROM python:3.11

# Slim picture — minimal Debian base
FROM python:3.11-slim

# Alpine picture — even smaller, musl-based Linux
FROM python:3.11-alpine

Erstellen Sie nun jeweils ein Bild und überprüfen Sie die Größen:

docker photographs | grep python

Sie werden einen Unterschied von mehreren hundert Megabyte feststellen, wenn Sie nur eine Zeile in Ihrer Docker-Datei ändern. Was sollten Sie additionally verwenden?

  • schlank ist die sicherere Standardeinstellung für die meisten Python-Projekte. Es entfernt unnötige Instruments, behält aber die C-Bibliotheken bei, die viele Python-Pakete für die korrekte Set up benötigen.
  • alpin ist noch kleiner, verwendet aber eine andere C-Bibliothek – musl anstatt glibc – Dies kann zu Kompatibilitätsproblemen mit bestimmten Python-Paketen führen. Daher verbringen Sie möglicherweise mehr Zeit damit, fehlgeschlagene Pip-Installationen zu debuggen, als Sie an Bildgröße sparen.

Faustregel: Beginnen Sie mit Python:3.1x-slim. Wechseln Sie nur dann zu Alpine, wenn Sie sicher sind, dass Ihre Abhängigkeiten kompatibel sind und Sie eine zusätzliche Größenreduzierung benötigen.

// Ordnen von Ebenen zur Maximierung des Caches

Docker erstellt Bilder Schicht für Schicht, eine Anweisung nach der anderen. Sobald eine Ebene erstellt wurde, wird sie von Docker zwischengespeichert. Wenn sich beim nächsten Construct nichts geändert hat, was sich auf einen Layer auswirken würde, verwendet Docker die zwischengespeicherte Model wieder und überspringt die Neuerstellung.

Der Haken: Wenn sich eine Ebene ändert, wird jede darauffolgende Ebene ungültig gemacht und von Grund auf neu erstellt.

Dies ist für die Abhängigkeitsinstallation von großer Bedeutung. Hier ist ein häufiger Fehler:

# Dangerous layer order — dependencies reinstall on each code change
FROM python:3.11-slim

WORKDIR /app

COPY . .                          # copies every part, together with your code
RUN pip set up -r necessities.txt   # runs AFTER the copy, so it reruns each time any file modifications

Jedes Mal, wenn Sie eine einzelne Zeile in Ihrem Skript ändern, macht Docker diese ungültig COPY . . Layer und installiert dann alle Ihre Abhängigkeiten von Grund auf neu. Bei einem Projekt mit einem schweren necessities.txtdas sind Minuten, die professional Wiederherstellung verschwendet werden.

Die Lösung ist einfach: Kopieren Sie zuerst die Dinge, die sich am wenigsten ändern.

# Good layer order — dependencies cached until necessities.txt modifications
FROM python:3.11-slim

WORKDIR /app

COPY necessities.txt .           # copy solely necessities first
RUN pip set up --no-cache-dir -r necessities.txt   # set up deps — this layer is cached

COPY . .                          # copy your code final — solely this layer reruns on code modifications

CMD ("python", "app.py")

Jetzt, wenn du dich änderst app.pyDocker verwendet die zwischengespeicherte Pip-Ebene erneut und führt nur die letzte erneut aus COPY . ..

Faustregel: Bestellen Sie Ihr COPY Und RUN Anweisungen von „am seltensten geändert“ bis „am häufigsten geändert“. Abhängigkeiten vor dem Code, immer.

# Verwendung mehrstufiger Builds

Einige Instruments werden nur zur Construct-Zeit benötigt – Compiler, Testläufer, Construct-Abhängigkeiten –, aber sie landen trotzdem in Ihrem endgültigen Picture und blähen es mit Dingen auf, die die laufende Anwendung nie berührt.

Mehrstufige Builds lösen dieses Drawback. In einem Schritt erstellen oder installieren Sie alles, was Sie benötigen, und kopieren dann nur die fertige Ausgabe in ein sauberes, minimales endgültiges Picture. Die Construct-Instruments schaffen es nie in das von Ihnen versendete Picture.

Hier ist ein Python-Beispiel, bei dem wir Abhängigkeiten installieren, das endgültige Bild aber schlank halten möchten:

# Single-stage — construct instruments find yourself within the closing picture
FROM python:3.11-slim

WORKDIR /app

RUN apt-get replace && apt-get set up -y gcc build-essential
COPY necessities.txt .
RUN pip set up --no-cache-dir -r necessities.txt

COPY . .
CMD ("python", "app.py")

Jetzt mit mehrstufigem Aufbau:

# Multi-stage — construct instruments keep within the builder stage solely

# Stage 1: builder — set up dependencies
FROM python:3.11-slim AS builder

WORKDIR /app

RUN apt-get replace && apt-get set up -y gcc build-essential

COPY necessities.txt .
RUN pip set up --no-cache-dir --prefix=/set up -r necessities.txt

# Stage 2: runtime — clear picture with solely what's wanted
FROM python:3.11-slim

WORKDIR /app

# Copy solely the put in packages from the builder stage
COPY --from=builder /set up /usr/native

COPY . .

CMD ("python", "app.py")

Die Instruments gcc und build-essential – die zum Kompilieren einiger Python-Pakete erforderlich sind – sind aus dem endgültigen Picture nicht mehr enthalten. Die App funktioniert weiterhin, da die kompilierten Pakete kopiert wurden. Die Construct-Instruments selbst blieben in der Builder-Part zurück, die Docker verwirft. Dieses Muster ist in Go- oder Node.js-Projekten noch wirkungsvoller, wo ein Compiler oder Knotenmodule mit Hunderten von Megabyte vollständig aus dem ausgelieferten Picture ausgeschlossen werden können.

# Aufräumen innerhalb der Installationsschicht

Wenn Sie Systempakete mit installieren apt-getlädt der Paketmanager Paketlisten herunter und speichert Dateien zwischen, die Sie zur Laufzeit nicht benötigen. Wenn Sie sie separat löschen RUN Gemäß der Anweisung existieren sie immer noch in der Zwischenschicht, und das Schichtensystem von Docker bedeutet, dass sie immer noch zur endgültigen Bildgröße beitragen.

Um sie tatsächlich zu entfernen, muss die Bereinigung dort erfolgen RUN Anweisungen wie bei der Set up.

# Cleanup in a separate layer — cached recordsdata nonetheless bloat the picture
FROM python:3.11-slim

RUN apt-get replace && apt-get set up -y curl
RUN rm -rf /var/lib/apt/lists/* # already dedicated within the layer above

# Cleanup in the identical layer — nothing is dedicated to the picture
FROM python:3.11-slim

RUN apt-get replace && apt-get set up -y curl 
    && rm -rf /var/lib/apt/lists/*

Die gleiche Logik gilt für andere Paketmanager und temporäre Dateien.

Faustregel: beliebig apt-get set up sollte befolgt werden && rm -rf /var/lib/apt/lists/* im selben RUN Befehl. Machen Sie es zur Gewohnheit.

# Implementieren von .dockerignore-Dateien

Wenn du rennst docker constructsendet Docker alles im Construct-Verzeichnis als Construct-Kontext an den Docker-Daemon. Dies geschieht, bevor Anweisungen in Ihrer Docker-Datei ausgeführt werden, und enthält häufig Dateien, die Sie mit ziemlicher Sicherheit nicht in Ihrem Picture haben möchten.

Ohne a .dockerignore Datei senden Sie Ihren gesamten Projektordner: .git Verlauf, virtuelle Umgebungen, lokale Datendateien, Testvorrichtungen, Editorkonfigurationen und mehr. Dadurch wird jeder Construct verlangsamt und es besteht die Gefahr, dass vertrauliche Dateien in Ihr Picture kopiert werden.

A .dockerignore Datei funktioniert genauso wie .gitignore; Es teilt Docker mit, welche Dateien und Ordner aus dem Construct-Kontext ausgeschlossen werden sollen.

Hier ist ein Beispiel, wenn auch gekürzt: .dockerignore für ein typisches Python-Datenprojekt:

# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
*.egg-info/

# Digital environments
.venv/
venv/
env/

# Information recordsdata (do not bake massive datasets into photographs)
information/
*.csv
*.parquet
*.xlsx

# Jupyter
.ipynb_checkpoints/
*.ipynb

...

# Exams
assessments/
pytest_cache/
.protection

...

# Secrets and techniques — by no means let these into a picture
.env
*.pem
*.key

Dies führt zu einer erheblichen Reduzierung der an den Docker-Daemon gesendeten Daten, bevor der Construct überhaupt beginnt. Bei großen Datenprojekten mit Parquet-Dateien oder Roh-CSVs im Projektordner kann dies der größte Einzelgewinn aller fünf Vorgehensweisen sein.

Es gibt auch einen erwähnenswerten Sicherheitsaspekt. Wenn Ihr Projektordner enthält .env Dateien mit API-Schlüsseln oder Datenbankanmeldeinformationen vergessen .dockerignore bedeutet, dass diese Geheimnisse in Ihr Picture eingebrannt werden könnten – insbesondere, wenn Sie eine Frau haben COPY . . Anweisung.

Faustregel: Immer hinzufügen .env und alle Anmeldeinformationsdateien an .dockerignore zusätzlich zu Datendateien, die nicht in das Bild eingebrannt werden müssen. Auch verwenden Docker-Geheimnisse für smart Daten.

# Zusammenfassung

Keine dieser Techniken erfordert fortgeschrittene Docker-Kenntnisse; Es sind eher Gewohnheiten als Techniken. Wenn Sie sie konsequent anwenden, werden Ihre Pictures kleiner, Ihre Builds schneller und Ihre Bereitstellungen sauberer.

Üben Was es behebt
Schlankes/alpines Grundbild

Stellt kleinere Pictures sicher, indem nur mit wesentlichen Betriebssystempaketen begonnen wird.

Ebenenreihenfolge

Vermeidet die Neuinstallation von Abhängigkeiten bei jeder Codeänderung.

Mehrstufige Builds

Schließt Construct-Instruments vom endgültigen Picture aus.

Bereinigung auf gleicher Ebene

Verhindert, dass der Apt-Cache Zwischenschichten aufbläht.

.dockerignore

Reduziert den Construct-Kontext und hält Geheimnisse von Bildern fern.

Viel Spaß beim Codieren!

Bala Priya C ist ein Entwickler und technischer Redakteur aus Indien. Sie arbeitet gerne an der Schnittstelle von Mathematik, Programmierung, Datenwissenschaft und Inhaltserstellung. Zu ihren Interessen- und Fachgebieten gehören DevOps, Datenwissenschaft und Verarbeitung natürlicher Sprache. Sie liebt es zu lesen, zu schreiben, zu programmieren und Kaffee zu trinken! Derzeit arbeitet sie daran, zu lernen und ihr Wissen mit der Entwickler-Neighborhood zu teilen, indem sie Tutorials, Anleitungen, Meinungsbeiträge und mehr verfasst. Bala erstellt außerdem ansprechende Ressourcenübersichten und Programmier-Tutorials.



Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert