Docker für Python- und Datenprojekte: Ein Leitfaden für Anfänger
Bild vom Autor

# Einführung

Python und Datenprojekte haben ein Abhängigkeitsproblem. Zwischen Python-Versionen, virtuellen Umgebungen, Paketen auf Systemebene und Betriebssystemunterschieden kann es manchmal länger dauern, den Code einer anderen Individual auf Ihrem Pc zum Laufen zu bringen, als den Code selbst zu verstehen.

Docker löst dieses Drawback, indem Sie Ihren Code und seine gesamte Umgebung – Python-Model, Abhängigkeiten, Systembibliotheken – in einem einzigen Artefakt namens Picture packen. Von dem Picture aus können Sie Container starten, die auf Ihrem Laptop computer, dem Pc Ihres Teamkollegen und einem Cloud-Server identisch laufen. Sie beenden das Debuggen von Umgebungen und beginnen mit der Auslieferung der Arbeit.

In diesem Artikel lernen Sie Docker anhand praktischer Beispiele kennen, wobei der Schwerpunkt auf Datenprojekten liegt: Containerisierung eines Skripts, Bereitstellung eines Modells für maschinelles Lernen FastAPIVerkabelung einer Multi-Service-Pipeline mit Docker Composeund Planen eines Jobs mit einem Cron-Container.

# Voraussetzungen

Bevor Sie die Beispiele durcharbeiten, benötigen Sie:

  • Docker und Docker Compose für Ihr Betriebssystem installiert. Folgen Sie dem Offizielle Installationsanleitung für Ihre Plattform.
  • Vertrautheit mit der Befehlszeile und Python.
  • Vertrautheit mit dem Schreiben einer Docker-Datei, dem Erstellen eines Photographs und dem Ausführen eines Containers aus diesem Picture.

Wenn Sie eine kurze Auffrischung wünschen, finden Sie hier einige Artikel, die Sie auf den neuesten Stand bringen:

Sie benötigen keine umfassenden Docker-Kenntnisse, um mitzumachen. Jedes Beispiel erklärt, was im Laufe der Zeit passiert.

# Containerisieren eines Python-Skripts mit angehefteten Abhängigkeiten

Beginnen wir mit dem häufigsten Anwendungsfall: Sie haben ein Python-Skript und ein necessities.txtund Sie möchten, dass es überall zuverlässig läuft.

Wir erstellen ein Datenbereinigungsskript, das eine CSV-Rohdatei für Verkäufe liest, Duplikate entfernt, fehlende Werte ergänzt und eine bereinigte Model auf die Festplatte schreibt.

// Strukturierung des Projekts

Das Projekt ist wie folgt organisiert:

data-cleaner/
├── Dockerfile
├── necessities.txt
├── clean_data.py
└── information/
    └── raw_sales.csv

// Das Drehbuch schreiben

Hier ist das Datenbereinigungsskript, das verwendet wird Pandas um die schwere Arbeit zu erledigen:

# clean_data.py
import pandas as pd
import os

INPUT_PATH = "information/raw_sales.csv"
OUTPUT_PATH = "information/cleaned_sales.csv"

print("Studying information...")
df = pd.read_csv(INPUT_PATH)
print(f"Rows earlier than cleansing: {len(df)}")

# Drop duplicate rows
df = df.drop_duplicates()

# Fill lacking numeric values with column median
for col in df.select_dtypes(embrace="quantity").columns:
    df(col) = df(col).fillna(df(col).median())

# Fill lacking textual content values with 'Unknown'
for col in df.select_dtypes(embrace="object").columns:
    df(col) = df(col).fillna('Unknown')

print(f"Rows after cleansing: {len(df)}")
df.to_csv(OUTPUT_PATH, index=False)
print(f"Cleaned file saved to {OUTPUT_PATH}")

// Abhängigkeiten anheften

Es ist wichtig, genaue Versionen anzuheften. Ohne es, pip set up pandas Möglicherweise werden unterschiedliche Versionen auf verschiedenen Computern installiert. Angepinnte Versionen garantieren, dass jeder das gleiche Verhalten erhält. Die genauen Versionen können Sie im festlegen necessities.txt Datei etwa so:

pandas==2.2.0
openpyxl==3.1.2

// Definieren der Docker-Datei

Diese Docker-Datei erstellt ein minimales, Cache-freundliches Picture für das Reinigungsskript:

# Use a slim Python 3.11 base picture
FROM python:3.11-slim

# Set the working listing contained in the container
WORKDIR /app

# Copy and set up dependencies first (for layer caching)
COPY necessities.txt .
RUN pip set up --no-cache-dir -r necessities.txt

# Copy the script into the container
COPY clean_data.py .

# Default command to run when the container begins
CMD ("python", "clean_data.py")

Hier gibt es einige Dinge, die es wert sind, erklärt zu werden. Wir verwenden python:3.11-slim anstelle des vollständigen Python-Photographs, da es wesentlich kleiner ist und nicht benötigte Pakete entfernt.

Wir kopieren necessities.txt bevor Sie den Relaxation des Codes kopieren. Dies ist beabsichtigt. Docker erstellt Bilder in Ebenen und speichert jedes einzelne im Cache. Wenn du dich nur änderst clean_data.pyDocker wird beim nächsten Construct nicht alle Ihre Abhängigkeiten neu installieren. Es verwendet die zwischengespeicherte Pip-Ebene wieder und springt direkt zum Kopieren Ihres aktualisierten Skripts. Mit dieser kleinen Bestellentscheidung können Sie Minuten beim Wiederaufbau einsparen.

// Bauen und Laufen

Nachdem das Picture erstellt wurde, können Sie den Container ausführen und Ihren lokalen Datenordner bereitstellen:

# Construct the picture and tag it
docker construct -t data-cleaner .

# Run it, mounting your native information/ folder into the container
docker run --rm -v $(pwd)/information:/app/information data-cleaner

Der -v $(pwd)/information:/app/information Flag mountet Ihr lokales information/ Ordner in den Container unter /app/information. Auf diese Weise liest das Skript Ihre CSV-Datei und die bereinigte Ausgabe wird auf Ihren Pc zurückgeschrieben. Es wird nichts in das Picture eingebrannt und die Daten verbleiben in Ihrem Dateisystem.

Der --rm Flag entfernt den Container automatisch, nachdem er fertig ist. Da es sich um ein einmaliges Skript handelt, gibt es keinen Grund, einen gestoppten Container herumliegen zu lassen.

# Bereitstellung eines Modells für maschinelles Lernen mit FastAPI

Sie haben ein Modell trainiert und möchten es über HTTP verfügbar machen, damit andere Dienste Daten senden und Vorhersagen zurückerhalten können. FastAPI funktioniert hierfür hervorragend: Es ist schnell, leichtgewichtig und übernimmt die Eingabevalidierung Pydantisch.

// Strukturierung des Projekts

Das Projekt trennt das Modellartefakt vom Anwendungscode:

ml-api/
├── Dockerfile
├── necessities.txt
├── app.py
└── mannequin.pkl

// Schreiben der App

Die folgende App lädt das Modell einmal beim Begin und stellt ein bereit /predict Endpunkt:

# app.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import pickle
import numpy as np

app = FastAPI(title="Gross sales Forecast API")

# Load the mannequin as soon as at startup
with open("mannequin.pkl", "rb") as f:
    mannequin = pickle.load(f)

class PredictRequest(BaseModel):
    area: str
    month: int
    marketing_spend: float
    units_in_stock: int

class PredictResponse(BaseModel):
    area: str
    predicted_revenue: float

@app.get("/well being")
def well being():
    return {"standing": "okay"}

@app.put up("/predict", response_model=PredictResponse)
def predict(request: PredictRequest):
    attempt:
        options = ((
            request.month,
            request.marketing_spend,
            request.units_in_stock
        ))
        prediction = mannequin.predict(options)
        return PredictResponse(
            area=request.area,
            predicted_revenue=spherical(float(prediction(0)), 2)
        )
    besides Exception as e:
        increase HTTPException(status_code=500, element=str(e))

Der PredictRequest Die Klasse führt die Eingabevalidierung für Sie durch. Wenn jemand eine Anfrage mit einem fehlenden Feld oder einer Zeichenfolge sendet, in der eine Zahl erwartet wird, lehnt FastAPI diese mit einer eindeutigen Fehlermeldung ab, bevor Ihr Modellcode überhaupt ausgeführt wird. Das Modell wird einmal beim Begin geladen – nicht bei jeder Anfrage – wodurch die Antwortzeiten kurz bleiben.

Der /well being endpoint ist eine kleine, aber wichtige Ergänzung: Docker, Load Balancer und Cloud-Plattformen prüfen damit, ob Ihr Dienst tatsächlich betriebsbereit ist.

// Definieren der Docker-Datei

Diese Docker-Datei backt das Modell direkt in das Picture, sodass der Container vollständig eigenständig ist:

FROM python:3.11-slim

WORKDIR /app

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

# Copy the mannequin and the app collectively
COPY mannequin.pkl .
COPY app.py .

EXPOSE 8000

CMD ("uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000")

Der mannequin.pkl wird zum Zeitpunkt der Erstellung in das Bild integriert. Das bedeutet, dass der Container völlig eigenständig ist und Sie beim Ausführen nichts mounten müssen. Der --host 0.0.0.0 Flagge erzählt Uvicorn um alle Netzwerkschnittstellen im Container abzuhören, nicht nur localhost. Ohne dies können Sie die API nicht von außerhalb des Containers erreichen.

// Bauen und Laufen

Erstellen Sie das Picture und starten Sie den API-Server:

docker construct -t ml-api .
docker run --rm -p 8000:8000 ml-api

Testen Sie es mit Curl:

curl -X POST http://localhost:8000/predict 
  -H "Content material-Kind: software/json" 
  -d '{"area": "North", "month": 3, "marketing_spend": 5000.0, "units_in_stock": 320}'

# Erstellen einer Multi-Service-Pipeline mit Docker Compose

Echte Datenprojekte umfassen selten nur einen Prozess. Möglicherweise benötigen Sie eine Datenbank, ein Skript, das Daten hineinlädt, und ein Dashboard, das daraus liest – alles läuft zusammen.

Mit Docker Compose können Sie mehrere Container als eine einzige Anwendung definieren und ausführen. Jeder Dienst hat seinen eigenen Container, aber alle teilen sich ein privates Netzwerk, damit sie miteinander kommunizieren können.

// Strukturierung des Projekts

Die Pipeline teilt jeden Dienst in sein eigenes Unterverzeichnis auf:

pipeline/
├── docker-compose.yml
├── loader/
│   ├── Dockerfile
│   ├── necessities.txt
│   └── load_data.py
└── dashboard/
    ├── Dockerfile
    ├── necessities.txt
    └── app.py

// Definieren der Compose-Datei

Diese Compose-Datei deklariert alle drei Dienste und verbindet sie mit Integritätsprüfungen und gemeinsam genutzten URL-Umgebungsvariablen:

# docker-compose.yml
model: "3.9"

companies:

  db:
    picture: postgres:15
    surroundings:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: analytics
    volumes:
      - pgdata:/var/lib/postgresql/information
    healthcheck:
      check: ("CMD-SHELL", "pg_isready -U admin -d analytics")
      interval: 5s
      retries: 5

  loader:
    construct: ./loader
    depends_on:
      db:
        situation: service_healthy
    surroundings:
      DATABASE_URL: postgresql://admin:secret@db:5432/analytics

  dashboard:
    construct: ./dashboard
    depends_on:
      db:
        situation: service_healthy
    ports:
      - "8501:8501"
    surroundings:
      DATABASE_URL: postgresql://admin:secret@db:5432/analytics

volumes:
  pgdata:

// Schreiben des Loader-Skripts

Dieses Skript wartet kurz auf die Datenbank und lädt dann mithilfe von eine CSV-Datei in die Verkaufstabelle SQLAlchemy:

# loader/load_data.py
import pandas as pd
from sqlalchemy import create_engine
import os
import time

DATABASE_URL = os.environ("DATABASE_URL")

# Give the DB a second to be totally prepared
time.sleep(3)

engine = create_engine(DATABASE_URL)

df = pd.read_csv("sales_data.csv")
df.to_sql("gross sales", engine, if_exists="substitute", index=False)

print(f"Loaded {len(df)} rows into the gross sales desk.")

Schauen wir uns die Compose-Datei genauer an. Jeder Dienst wird in einem eigenen Container ausgeführt, sie befinden sich jedoch alle im selben von Docker verwalteten Netzwerk, sodass sie einander über den Dienstnamen als Hostnamen erreichen können. Der Lader verbindet sich mit db:5432 – und nicht localhost – weil db ist der Dienstname und Docker übernimmt die DNS-Auflösung automatisch.

Der Gesundheitscheck am PostgreSQL Service ist wichtig. depends_on allein wartet nur darauf, dass der Container startet, nicht darauf, dass PostgreSQL bereit ist, Verbindungen anzunehmen. Der Gesundheitscheck verwendet pg_isready um zu bestätigen, dass die Datenbank tatsächlich aktiv ist, bevor der Loader versucht, eine Verbindung herzustellen. Der pgdata Das Quantity behält die Datenbank zwischen den Läufen bei. Durch das Stoppen und Neustarten der Pipeline werden Ihre Daten nicht gelöscht.

// Alles anfangen

Rufen Sie alle Dienste mit einem einzigen Befehl auf:

docker compose up --build

Um alles zu stoppen, führen Sie Folgendes aus:

# Jobs mit einem Cron-Container planen

Manchmal muss ein Skript nach einem Zeitplan ausgeführt werden. Möglicherweise ruft es stündlich Daten von einer API ab und schreibt sie in eine Datenbank oder eine Datei. Für etwas so Einfaches möchten Sie kein vollständiges Orchestrierungssystem wie Airflow einrichten. Ein Cron-Container erledigt die Arbeit sauber.

// Strukturierung des Projekts

Das Projekt enthält neben dem Skript und der Docker-Datei eine Crontab-Datei:

data-fetcher/
├── Dockerfile
├── necessities.txt
├── fetch_data.py
└── crontab

// Schreiben des Abrufskripts

Dieses Skript verwendet Anfragen um einen API-Endpunkt zu erreichen und die Ergebnisse als zeitgestempelte CSV-Datei zu speichern:

# fetch_data.py
import requests
import pandas as pd
from datetime import datetime
import os

API_URL = "https://api.instance.com/gross sales/newest"
OUTPUT_DIR = "/app/output"

os.makedirs(OUTPUT_DIR, exist_ok=True)

print(f"({datetime.now()}) Fetching information...")

response = requests.get(API_URL, timeout=10)
response.raise_for_status()

information = response.json()
df = pd.DataFrame(information("data"))

timestamp = datetime.now().strftime("%Ypercentmpercentd_percentHpercentM")
output_path = f"{OUTPUT_DIR}/sales_{timestamp}.csv"
df.to_csv(output_path, index=False)

print(f"({datetime.now()}) Saved {len(df)} data to {output_path}")

// Definieren der Crontab

Die Crontab plant die stündliche Ausführung des Skripts und leitet alle Ausgaben in eine Protokolldatei um:

# Run each hour, on the hour
0 * * * * python /app/fetch_data.py >> /var/log/fetch.log 2>&1

Der >> /var/log/fetch.log 2>&1 Der Teil leitet sowohl die Standardausgabe als auch die Fehlerausgabe in eine Protokolldatei um. So untersuchen Sie, was im Nachhinein passiert ist.

// Definieren der Docker-Datei

Diese Docker-Datei installiert cron, registriert den Zeitplan und sorgt dafür, dass er im Vordergrund läuft:

FROM python:3.11-slim

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

WORKDIR /app

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

COPY fetch_data.py .
COPY crontab /and many others/cron.d/fetch-job

# Set appropriate permissions and register the crontab
RUN chmod 0644 /and many others/cron.d/fetch-job && crontab /and many others/cron.d/fetch-job

# cron -f runs cron within the foreground, which is required for Docker
CMD ("cron", "-f")

Der cron -f Flagge ist hier wichtig. Docker hält einen Container am Leben, solange sein Hauptprozess läuft. Wenn cron im Hintergrund ausgeführt würde (Standardeinstellung), würde der Hauptprozess sofort beendet und Docker würde den Container stoppen. Der -f Flag sorgt dafür, dass Cron im Vordergrund läuft, sodass der Container am Leben bleibt.

// Bauen und Laufen

Erstellen Sie das Picture und starten Sie den Container im getrennten Modus:

docker construct -t data-fetcher .
docker run -d --name fetcher -v $(pwd)/output:/app/output data-fetcher

Überprüfen Sie jederzeit die Protokolle:

docker exec fetcher cat /var/log/fetch.log

Der Ausgabeordner wird von Ihrem lokalen Pc bereitgestellt, sodass die CSV-Dateien in Ihrem Dateisystem landen, obwohl das Skript im Container ausgeführt wird.

# Zusammenfassung

Ich hoffe, Sie fanden diesen Docker-Artikel hilfreich. Docker muss nicht kompliziert sein. Beginnen Sie mit dem ersten Beispiel, tauschen Sie Ihr eigenes Skript und Ihre Abhängigkeiten ein und machen Sie sich mit dem Construct-Run-Zyklus vertraut. Sobald Sie das getan haben, folgen die anderen Muster ganz natürlich. Docker passt intestine, wenn:

  • Sie benötigen reproduzierbare Umgebungen für alle Maschinen oder Teammitglieder
  • Sie geben Skripte oder Modelle frei, für die bestimmte Abhängigkeitsanforderungen gelten
  • Sie bauen Multi-Service-Systeme auf, die zuverlässig zusammenarbeiten müssen
  • Sie möchten die Bereitstellung überall ohne Reibungsverluste durchführen

Allerdings müssen Sie nicht immer Docker für Ihre gesamte Python-Arbeit verwenden. Es ist wahrscheinlich übertrieben, wenn:

  • Sie führen schnelle, explorative Analysen nur für sich selbst durch
  • Ihr Skript weist über die Standardbibliothek hinaus keine externen Abhängigkeiten auf
  • Sie stehen am Anfang eines Projekts und Ihre Anforderungen ändern sich schnell

Wenn Sie daran interessiert sind, noch weiter zu gehen, schauen Sie hier vorbei 5 einfache Schritte zur Beherrschung von Docker für Information Science.

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