Docker und Rust: Containerisierung von Anwendungen mit Rust

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Docker und Rust das ideale Paar sind

Rust ist eine moderne Systemprogrammiersprache, die für ihre Leistung und Speichersicherheit bekannt ist. Um eine Rust-Anwendung jedoch zum Endbenutzer oder in die Cloud zu bringen, muss das Problem der Umgebung gelöst werden. Hier kommt Docker ins Spiel. Die Containerisierung ermöglicht es, eine Rust-Anwendung zusammen mit all ihren Abhängigkeiten in einen leichten und isolierten Container zu packen. In diesem Artikel werden wir untersuchen, wie man mit bewährten Methoden ein effizientes und minimales Docker-Image für ein Rust-Projekt erstellt.



1. Grundlagen von Docker für Rust-Entwickler

Docker ist eine Plattform zum Entwickeln, Bereitstellen und Ausführen von Anwendungen in Containern. Ein Container enthält die Anwendung selbst und alles, was für ihren Betrieb benötigt wird: Bibliotheken, Systemdienstprogramme und Konfigurationen. Für Rust ist dies besonders relevant, da die kompilierte Binärdatei nicht von einer Laufzeitumgebung abhängt (im Gegensatz zu Python oder Node.js), was die Erstellung sehr kleiner Images ermöglicht.

Die wichtigsten Komponenten, die Sie benötigen:

  • Dockerfile — eine Textdatei mit Anweisungen zum Erstellen des Images.
  • .dockerignore — eine Datei, die unnötige Dateien aus dem Build-Kontext ausschließt.
  • Docker Compose (optional) — zur Orchestrierung mehrerer Container.

Stellen Sie vor dem Start sicher, dass Sie Docker Desktop oder die Docker Engine installiert haben.



2. Erstellen eines Dockerfile für eine Rust-Anwendung

Betrachten wir ein einfaches Beispiel eines Webservers in Rust unter Verwendung des Frameworks actix-web. Unsere Hauptdatei main.rs sieht wie folgt aus:

use actix_web::{web, App, HttpServer, Responder};

async fn index() -> impl Responder { "Hello, Docker and Rust!"}

#[actix_web::main]async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().route("/", web::get().to(index)) }) .bind("0.0.0.0:8080")? .run() .await}

Jetzt erstellen wir das Dockerfile. Die wichtigste Technik hier ist der Multi-Stage-Build. Er ermöglicht es, die Anwendung zunächst in einer Umgebung mit dem vollständigen Rust-Toolset zu erstellen und dann die fertige Binärdatei in ein minimales endgültiges Image zu kopieren.

// ---- Erste Stufe: Build ----FROM rust:1.75 as builder

WORKDIR /app

// Manifeste kopieren, um Abhängigkeiten zu cachenCOPY Cargo.toml Cargo.lock ./

// Leere main.rs erstellen, um Abhängigkeiten zu bauenRUN mkdir src && echo "fn main() {}" > src/main.rsRUN cargo build --release 2>/dev/null || true

// Jetzt den eigentlichen Quellcode kopierenCOPY src ./src

// Finale Binärdatei bauen (Abhängigkeiten sind bereits gecached)RUN cargo build --release

// ---- Zweite Stufe: Finales Image ----FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*

WORKDIR /app

// Binärdatei aus der ersten Stufe kopierenCOPY --from=builder /app/target/release/my_rust_app .

EXPOSE 8080

CMD ["./my_rust_app"]

Beachten Sie den Trick mit der leeren main.rs. Dadurch kann Docker die kompilierten Abhängigkeiten (crates) cachen und sie nicht jedes Mal neu erstellen, wenn Sie nur den Quellcode ändern. Dies beschleunigt wiederholte Builds erheblich.



2.1. Optimierung der Image-Größe

Das endgültige Image basierend auf debian:bookworm-slim wiegt etwa 80-100 MB. Wenn Sie jedoch ein wirklich minimales Image wünschen, können Sie scratch (leeres Image) oder alpine verwenden. Für statisch kompilierte Rust-Anwendungen ist dies die ideale Wahl. Dazu muss das Build-Target geändert werden:

// In der ersten Stufe (builder):RUN rustup target add x86_64-                

Blogs

Buchempfehlungen