Rust #
Rust sering diposisikan sebagai “bahasa paling ideal” untuk container karena mampu menghasilkan single static binary. Akibatnya, banyak engineer mengira Docker untuk Rust itu trivial: build → copy binary → selesai.
Realitanya, Rust di production tetap punya jebakan:
- image membengkak karena glibc
- build time lama
- TLS & libc dependency tidak disadari
- debug & observability sering diabaikan
Artikel ini membahas strategi Docker image Rust yang kecil, aman, dan benar-benar production-grade, bukan sekadar demo FROM scratch.
Realita Ukuran Docker Image Rust #
Tanpa Strategi #
| Setup | Ukuran Image |
|---|---|
| rust:latest (single stage) | 1.2–1.6 GB |
| rust + slim runtime | 150–250 MB |
Dengan Strategi yang Benar #
| Setup | Ukuran Image |
|---|---|
| Multi-stage + slim | 40–80 MB |
| Distroless | 15–40 MB |
| Scratch (static) | 5–15 MB ⭐ |
Masalah Utama Rust di Docker #
1. Build Toolchain Sangat Besar #
- rustc
- cargo
- LLVM
Semua ini harus 100% berhenti di build stage.
2. Static Binary Itu Opsional, Bukan Default #
Secara default:
- Rust link ke glibc
- butuh runtime OS
Static binary harus disengaja.
3. TLS & libc adalah Silent Dependency #
Crate seperti:
reqwestopensslnative-tls
Bisa menarik dependency runtime tanpa disadari.
Prinsip Utama Image Rust Production #
Runtime image Rust idealnya hanya berisi binary + cert (opsional).
Tidak ada:
- shell
- package manager
- OS tool
Strategi 1: Multi-stage Build (Wajib) #
Dockerfile Dasar #
FROM rust:1.76 AS builder
WORKDIR /app
# Cache dependency
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release
# Build real app
COPY src ./src
RUN cargo build --release
FROM debian:12-slim
WORKDIR /app
COPY --from=builder /app/target/release/app ./app
CMD ["./app"]
Ukuran: 40–80 MB.
Strategi 2: Distroless Rust #
FROM rust:1.76 AS builder
WORKDIR /app
COPY . .
RUN cargo build --release
FROM gcr.io/distroless/cc-debian12
WORKDIR /app
COPY --from=builder /app/target/release/app ./app
CMD ["./app"]
Ukuran: 15–40 MB.
Catatan:
- cocok untuk glibc binary
- debugging minimal
Strategi 3: Static Binary + Scratch (Paling Kecil) #
Build Static #
FROM rust:1.76 AS builder
WORKDIR /app
RUN rustup target add x86_64-unknown-linux-musl
COPY . .
RUN cargo build --release --target x86_64-unknown-linux-musl
FROM scratch
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/app /app
CMD ["/app"]
Ukuran: 5–15 MB.
TLS & Certificate #
Static binary tidak membawa CA cert.
Solusi:
- embed cert
- atau copy dari builder
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
Optimasi Binary Size #
Gunakan:
RUSTFLAGS="-C strip=symbols" \
cargo build --release
Atau:
strip target/release/app
Tambahan:
- LTO
panic = "abort"
Observability & Production Concerns #
Logging #
- structured logging
- STDOUT
Metrics #
- expose
/metrics
Healthcheck #
- HTTP based
Security & Runtime Safety #
| Aspek | Rust |
|---|---|
| Memory safety | ✅ |
| Non-root | Default |
| Attack surface | Sangat kecil |
Perbandingan Strategi #
| Strategi | Ukuran | Kompleksitas | Rekomendasi |
|---|---|---|---|
| debian-slim | Sedang | Rendah | Default |
| distroless | Kecil | Menengah | Production |
| scratch | Sangat kecil | Tinggi | High performance |
Kapan Strategi Mana Digunakan? #
| Kondisi | Pilihan |
|---|---|
| Microservice | distroless |
| High security | scratch |
| Banyak native TLS | distroless |
Penutup #
Rust adalah bahasa paling dekat dengan ideal container runtime, tapi tetap bisa gagal di production jika:
- dependency tidak dipahami
- TLS & libc diabaikan
- observability dilupakan
Docker image kecil di Rust bukan prestasi, tapi baseline. Yang membedakan engineer matang adalah stabilitas, security, dan operasionalnya.
Rust membuat image kecil itu mudah. Engineering membuatnya layak production.