Docker und Rust: Containerisierung von Anwendungen von A bis Z

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 ein ideales Paar sind



Moderne Softwareentwicklung erfordert nicht nur das Schreiben von effizientem Code, sondern auch die Schaffung einer zuverlässigen Umgebung für dessen Ausführung. Rust – eine Systemprogrammiersprache, bekannt für ihre Leistung und Speichersicherheit – eignet sich ideal für die Erstellung hochbelasteter Dienste. Docker wiederum bietet leichte und isolierte Container, mit denen Sie die Anwendung samt aller Abhängigkeiten verpacken können.



Die Kombination dieser beiden Technologien gibt Entwicklern ein mächtiges Werkzeug: Eine kompilierte Rust-Binärdatei, platziert in einem minimalen Container, läuft schnell, sicher und vorhersagbar auf jeder Plattform. In diesem Artikel gehen wir den Weg von einem einfachen Beispiel bis zu einer Production-Ready-Lösung, analysieren typische Fehler und lernen, Images zu optimieren.



Grundlagen: Erstellen einer einfachen Rust-Anwendung in Docker



Schritt 1: Vorbereitung des Rust-Projekts



Erstellen wir zunächst eine einfache Webanwendung in Rust mit dem beliebten Framework actix-web. Dies ist nicht zwingend erforderlich, bietet aber ein anschauliches Beispiel für die Arbeit mit dem Netzwerk innerhalb eines Containers.



Erstellen Sie ein neues Projekt:



cargo new rust-docker-appcd rust-docker-app


Fügen Sie die Abhängigkeit in Cargo.toml hinzu:



[dependencies]actix-web = "4"


Ersetzen Sie den Inhalt von src/main.rs durch:



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

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

#[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}


Schritt 2: Einfaches Dockerfile



Ein einfaches Dockerfile für eine Rust-Anwendung sieht so aus:



FROM rust:latest

WORKDIR /appCOPY . .

RUN cargo build --release

EXPOSE 8080

CMD ["./target/release/rust-docker-app"]


Dieser Ansatz funktioniert, hat aber gravierende Nachteile: Das Image wird sehr groß (über 1 GB) und jeder Neubuild lädt alle Abhängigkeiten erneut herunter.



Optimierung: Multi-Stage-Build und Reduzierung der Image-Größe



Multi-Stage-Build



Die Schlüsseltechnik für Rust-Entwickler ist die Verwendung eines Multi-Stage-Builds. Die Idee ist einfach: In der ersten Stufe verwenden wir ein vollständiges Image mit Compiler und Tools, in der zweiten Stufe ein minimales Image, in das wir nur die fertige Binärdatei kopieren.



# Stufe 1: BuildFROM rust:latest AS builder

WORKDIR /appCOPY Cargo.toml Cargo.lock ./RUN mkdir src && echo "fn main() {}" > src/main.rsRUN cargo build --release 2>/dev/null || true

COPY src/ src/RUN cargo build --release

# Stufe 2: Minimales ImageFROM debian:bookworm-slim

WORKDIR /appCOPY --from=builder /app/target/release/rust-docker-app .

EXPOSE 8080CMD ["./rust-docker-app"]


Warum funktioniert das? Der erste RUN cargo build cached die Abhängigkeiten. Wenn Sie nur den Quellcode ändern, baut Docker die Abhängigkeiten nicht neu, was den Build erheblich beschleunigt.



Verwendung von Alpine für maximale Komprimierung



Wenn Sie eine minimale Image-Größe benötigen, verwenden Sie alpine als finale Stufe. Rust-Binärdateien werden statisch gelinkt, daher sind keine zusätzlichen Bibliotheken erforderlich.



# Finale Stufe mit AlpineFROM alpine:latest

WORKDIR /appCOPY --from=builder /app/target/release/rust-docker-app .

EXPOSE 8080CMD ["./rust-docker-app"]


Die Image-Größe kann dabei nur 5–15 MB betragen, statt 1+ GB!



Fortgeschrittene Techniken: Caching und Sicherheit



Caching von Abhängigkeiten mit sccache



Für große Projekte kann

Blogs

Buchempfehlungen