Docker und Rust: Containerisierung von Anwendungen für die Produktion

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 ein Rust-Entwickler Docker braucht

Rust ist bekannt für seine Leistung und Speichersicherheit, aber selbst die effizienteste Binärdatei benötigt die richtige Umgebung zum Ausführen. Docker löst dieses Problem, indem es die Anwendung zusammen mit allen Abhängigkeiten in einen isolierten Container packt. In diesem Artikel werden wir untersuchen, wie man Rust-Anwendungen mit Docker containerisiert, unter Verwendung moderner Techniken, einschließlich Multi-Stage-Builds und Minimierung der Image-Größe.

Die Containerisierung von Rust-Projekten ist besonders vorteilhaft, da Rust in eine statische Binärdatei kompiliert wird – dies ermöglicht die Erstellung minimaler Images (alpine oder sogar scratch), die schneller und sicherer laufen als vergleichbare Anwendungen in Python oder Node.js.



1. Grundlagen: Dockerfile für eine einfache Rust-Anwendung

Beginnen wir mit einem einfachen Webserver in Rust unter Verwendung des Frameworks actix-web. Erstellen wir ein grundlegendes Dockerfile.



1.1. Projektstruktur

my_rust_app/├── Cargo.toml├── Cargo.lock└── src/    └── main.rs


1.2. Beispielcode (main.rs)

use actix_web::{get, App, HttpResponse, HttpServer, Responder};

#[get("/")]async fn hello() -> impl Responder { HttpResponse::Ok().body("Hallo aus dem Rust-Container!")}

#[actix_web::main]async fn main() -> std::io::Result<()> { HttpServer::new(|| App::new().service(hello)) .bind("0.0.0.0:8080")? .run() .await}


1.3. Einfaches Dockerfile

FROM rust:1.77 AS builderWORKDIR /appCOPY Cargo.toml Cargo.lock ./RUN mkdir src && echo "fn main() {}" > src/main.rsRUN cargo build --releaseCOPY src/ src/RUN cargo build --release

FROM debian:bookworm-slimCOPY --from=builder /app/target/release/my_rust_app /usr/local/bin/EXPOSE 8080CMD ["my_rust_app"]

Erklärung: Die erste Stufe (builder) kompiliert die Anwendung, die zweite Stufe kopiert nur die Binärdatei in ein sauberes Debian-Image. Dies reduziert die Größe von ~2 GB auf ~100 MB.



2. Multi-Stage-Build: Optimierung der Image-Größe

Multi-Stage-Build ist eine Schlüsseltechnik für Rust. Sie ermöglicht es, die Build-Umgebung (mit Compiler, Abhängigkeiten) von der Laufzeitumgebung zu trennen.



2.1. Fortschrittliches Dockerfile mit Caching

Um wiederholte Builds zu beschleunigen, cachen wir die Abhängigkeiten:

FROM rust:1.77 AS builderWORKDIR /appCOPY Cargo.toml Cargo.lock ./RUN mkdir src && echo "fn main() {}" > src/main.rsRUN cargo build --release 2>/dev/null || trueCOPY src/ src/RUN cargo build --release && \    cp target/release/my_rust_app /app/rust_app

FROM gcr.io/distroless/cc-debian12COPY --from=builder /app/rust_app /app/rust_appEXPOSE 8080CMD ["/app/rust_app"]

Warum distroless? Das distroless-Image enthält nur glibc und grundlegende Bibliotheken – ohne shell, apt, ls. Dies erhöht die Sicherheit und reduziert die Größe auf ~30 MB.



2.2. Minimales Image auf scratch-Basis

Wenn Ihre Anwendung libc nicht verwendet (z. B. mit #![no_std] geschrieben), kann scratch verwendet werden:

FROM rust:1.77 AS builderWORKDIR /appCOPY . .RUN cargo build --release

FROM scratchCOPY --from=builder /app/target/release/my_rust_app /appEXPOSE 8080CMD ["/app"]

Ein solches Image wiegt weniger als 10 MB!



3. Docker Compose: Multi-Container-Anwendung

Oft arbeitet eine Rust-Anwendung zusammen mit PostgreSQL, Redis oder Nginx. Wir verwenden docker-compose.yml:



3.1. Beispiel docker-compose.yml

version: '3.8'services:  app:    build: .    ports:      - "8080:8080"    environment:      - DATABASE_URL=postgres://user:pass@db:5432/mydb      - RUST_LOG=info    depends_on:      - db

db: image: postgres:16-alpine

Blogs

Buchempfehlungen