Docker und Rust: Containerisierung von Anwendungen auf fortgeschrittenem Niveau

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

Docker und Rust: Containerisierung von Anwendungen auf fortgeschrittenem Niveau



Die Containerisierung von Rust-Anwendungen mit Docker ist nicht einfach nur das Verpacken von Code in ein Image. Auf fortgeschrittenem Niveau ist es die Kunst, minimale, schnelle und sichere Container zu erstellen, die sich ideal für die Produktionsumgebung eignen. Rust, als systemnahe Programmiersprache, kompiliert zu nativem Code, was einzigartige Möglichkeiten zur Optimierung von Docker-Images bietet. In diesem Artikel betrachten wir Techniken, die über das einfache docker build hinausgehen, und zeigen, wie man effiziente Container für Rust-Anwendungen erstellt.



1. Multi-Stage-Build für Rust



Der Multi-Stage-Build ist ein Eckpfeiler der fortgeschrittenen Containerisierung von Rust. Er ermöglicht es, die Build-Umgebung (mit Compiler, Abhängigkeiten und Tools) vom finalen Image zu trennen, das nur die kompilierte Binärdatei und die notwendigen Laufzeitabhängigkeiten enthält.



Betrachten wir ein Beispiel eines Dockerfiles für einen Webserver mit actix-web:



# Stage 1: BuildFROM rust:1.75-slim-bullseye AS builder

WORKDIR /app

# Nur die Dateien mit Abhängigkeiten kopieren, um Layer zu cachenCOPY Cargo.toml Cargo.lock ./

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

# Jetzt den eigentlichen Quellcode kopierenCOPY src ./src

# Nur die geänderten Dateien neu kompilieren (Cache der Abhängigkeiten bleibt unberührt)RUN cargo build --release

# Stage 2: Finales ImageFROM debian:bullseye-slim

RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ libssl1.1 \ && rm -rf /var/lib/apt/lists/*

COPY --from=builder /app/target/release/my_app /usr/local/bin/my_app

USER nobodyEXPOSE 8080

CMD ["/usr/local/bin/my_app"]


Wichtige Optimierungen:

  • Caching von Abhängigkeiten: Zuerst werden nur Cargo.toml und Cargo.lock kopiert, dann die Abhängigkeiten kompiliert. Dies erlaubt Docker, den Layer-Cache zu nutzen, falls sich die Manifest-Dateien nicht geändert haben.
  • Minimales finales Image: Es wird debian:bullseye-slim anstelle des vollständigen Rust-Images verwendet. Dies reduziert die Größe von ~1,5 GB auf ~150 MB.
  • Sicherheit: Die Anwendung wird als Benutzer nobody ausgeführt, nicht als root.


2. Minimierung der Image-Größe: Von Alpine bis Scratch



Rust-Anwendungen benötigen keine Laufzeitumgebung wie eine Java Virtual Machine oder einen Python-Interpreter. Dies erlaubt die Verwendung minimaler Basis-Images.



Variante mit Alpine Linux:

FROM alpine:3.19 AS builderRUN apk add --no-cache musl-dev# ... Build ...

FROM alpine:3.19RUN apk add --no-cache ca-certificatesCOPY --from=builder /app/target/release/my_app /my_appCMD ["/my_app"]


Variante mit Scratch (leeres Image):

FROM alpine:3.19 AS builderRUN apk add --no-cache musl-dev# Build mit statischem LinkenRUN cargo build --release --target x86_64-unknown-linux-musl

FROM scratchCOPY --from=builder /app/target/x86_64-unknown-linux-musl/release/my_app /my_appCOPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/CMD ["/my_app"]


Vergleich der Image-Größen:

  • debian:bullseye-slim: ~80-150 MB (abhängig von der Anzahl der Systembibliotheken)
  • alpine:3.19: ~10-20 MB (verwendet musl libc anstelle von glibc)
  • scratch: ~5-10 MB (nur Binärdatei und Zertifikate)


Wichtig: Bei Verwendung von scratch muss sichergestellt werden, dass Ihre Anwendung keine dynamischen Bibliotheken benötigt. Verwenden Sie dazu statisches Linken mit dem Ziel

Blogs

Buchempfehlungen