Docker et Rust : conteneurisation d'applications pour la production

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : pourquoi un développeur Rust a-t-il besoin de Docker ?

Rust est réputé pour ses performances et sa sécurité mémoire, mais même le binaire le plus efficace nécessite un environnement approprié pour s'exécuter. Docker résout ce problème en empaquetant l'application avec toutes ses dépendances dans un conteneur isolé. Dans cet article, nous allons voir comment conteneuriser des applications Rust avec Docker, en utilisant des techniques modernes, notamment la construction multi-étapes et la minimisation de la taille de l'image.

La conteneurisation de projets Rust est particulièrement avantageuse car Rust compile en un binaire statique — cela permet de créer des images minimales (alpine ou même scratch), qui s'exécutent plus rapidement et de manière plus sécurisée que leurs équivalents en Python ou Node.js.



1. Les bases : Dockerfile pour une application Rust simple

Commençons par un serveur web simple en Rust utilisant le framework actix-web. Créons un Dockerfile de base.



1.1. Structure du projet

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


1.2. Exemple de code (main.rs)

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

#[get("/")]async fn hello() -> impl Responder { HttpResponse::Ok().body("Bonjour depuis le conteneur Rust !")}

#[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. Dockerfile simple

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"]

Explication : la première étape (builder) compile l'application, la deuxième étape copie uniquement le binaire dans une image Debian propre. Cela réduit la taille d'environ 2 Go à environ 100 Mo.



2. Construction multi-étapes : optimisation de la taille de l'image

La construction multi-étapes (multi-stage build) est une technique clé pour Rust. Elle permet de séparer l'environnement de construction (avec le compilateur, les dépendances) de l'environnement d'exécution.



2.1. Dockerfile avancé avec mise en cache

Pour accélérer les constructions répétées, mettons en cache les dépendances :

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"]

Pourquoi distroless ? L'image distroless contient uniquement glibc et les bibliothèques de base — sans shell, apt, ls. Cela améliore la sécurité et réduit la taille à environ 30 Mo.



2.2. Image minimale sur scratch

Si votre application n'utilise pas libc (par exemple, écrite avec #![no_std]), vous pouvez utiliser scratch :

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

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

Une telle image pèse moins de 10 Mo !



3. Docker Compose : application multi-conteneurs

Souvent, une application Rust fonctionne en tandem avec PostgreSQL, Redis ou Nginx. Utilisons docker-compose.yml :



3.1. Exemple de 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

Book Recommendations