Rocket #

Rocket adalah framework web Rust yang terkenal dengan ergonomi API, type-safety yang kuat, dan macro-based routing. Rocket sangat nyaman untuk developer Rust, namun memiliki karakteristik khusus:

  • Bergantung erat pada Rust nightly (pada versi tertentu) atau fitur compiler spesifik
  • Compile time relatif berat
  • Sangat sensitif terhadap konfigurasi environment

Karena itu, Docker untuk local development Rocket tidak boleh disamakan dengan Docker production. Artikel ini membahas secara mendalam dan rasional bagaimana membangun:

  • Dockerfile Rocket untuk local development
  • docker-compose.yml yang mendukung hot reload, volume mount, dan database
  • Best practice serta anti-pattern yang sering terjadi di proyek Rocket

Fokus utama: developer experience (DX), kecepatan iterasi, dan konsistensi environment.

Prinsip Docker Rocket #

Sebelum masuk ke konfigurasi, pahami dulu prinsip utamanya:

  1. Compile Rust mahal → dependency caching wajib
  2. Rocket sering restart saat development → hot reload penting
  3. Local dev ≠ production → image size bukan prioritas
  4. Source code harus di-mount → bukan di-copy berulang

Implikasi desain:

  • Gunakan image Rust resmi
  • Hindari distroless
  • Pisahkan Dockerfile dev & prod

Struktur Project Rocket #

.
├── Cargo.toml
├── Cargo.lock
├── src/
│   └── main.rs
├── Rocket.toml
├── Dockerfile
├── docker-compose.yml
└── .dockerignore

Dockerfile Rocket #

Contoh Dockerfile #

FROM rust:1.75-slim

# Install system dependencies
RUN apt-get update && apt-get install -y \
    pkg-config \
    libssl-dev \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# Install cargo-watch for hot reload
RUN cargo install cargo-watch

WORKDIR /app

# Copy manifest only (dependency cache)
COPY Cargo.toml Cargo.lock ./

# Dummy build to cache dependencies
RUN mkdir src && echo "fn main() {}" > src/main.rs \
    && cargo build \
    && rm -rf src

# Copy actual source code
COPY src ./src
COPY Rocket.toml ./Rocket.toml

EXPOSE 8000

CMD ["cargo", "watch", "-x", "run"]

Penjelasan Dockerfile #

Base Image #

FROM rust:1.75-slim

Alasan:

  • Toolchain Rust lengkap
  • Cocok untuk compile cepat
  • Lebih stabil untuk Rocket dibanding image minimal

System Dependencies #

libssl-dev

Digunakan untuk:

  • TLS
  • Database driver
  • Crate crypto

Tanpa dependency ini, build Rocket sering gagal secara silent.

Hot Reload dengan cargo-watch #

RUN cargo install cargo-watch

Manfaat:

  • Rebuild otomatis saat file berubah
  • Tidak perlu restart container
  • Feedback loop cepat

Dependency Caching Strategy #

COPY Cargo.toml Cargo.lock ./
RUN cargo build

Ini adalah pola wajib di Rust Docker:

  • Dependency hanya rebuild saat manifest berubah
  • Source code update tidak memicu rebuild dependency

Runtime Command #

CMD ["cargo", "watch", "-x", "run"]

Efek:

  • File berubah → compile ulang → Rocket restart
  • Cocok untuk local dev

Docker Compose Rocket #

Contoh docker-compose.yml #

version: "3.9"

services:
  app:
    build:
      context: .
    container_name: rocket_app
    volumes:
      - .:/app
      - cargo-registry:/usr/local/cargo/registry
      - cargo-git:/usr/local/cargo/git
    ports:
      - "8000:8000"
    environment:
      ROCKET_ENV: development
      ROCKET_ADDRESS: 0.0.0.0
      ROCKET_PORT: 8000
      DATABASE_URL: postgres://postgres:postgres@db:5432/app_db
    depends_on:
      - db

  db:
    image: postgres:16
    container_name: rocket_db
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: app_db
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  cargo-registry:
  cargo-git:
  postgres-data:

Penjelasan Docker Compose #

Volume Mount Source Code #

- .:/app
  • Edit kode di host
  • Rocket reload otomatis via cargo-watch

Cache Cargo Dependency #

- cargo-registry:/usr/local/cargo/registry
- cargo-git:/usr/local/cargo/git

Ini sangat penting:

  • Build ulang container jauh lebih cepat
  • Dependency tidak di-download ulang

Environment Rocket #

ROCKET_ADDRESS=0.0.0.0

Tanpa ini:

  • Rocket bind ke localhost
  • Tidak bisa diakses dari host

Contoh main.rs Rocket #

#[macro_use] extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello Rocket!"
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/", routes![index])
}

Rocket otomatis bind sesuai environment variable.


File Rocket.toml (Opsional) #

[default]
address = "0.0.0.0"
port = 8000
log_level = "debug"

Bisa menggantikan environment variable jika diinginkan.


.dockerignore (Wajib) #

target
.git
.env

Tanpa ini:

  • Context build besar
  • Cache Docker sering invalid

Workflow Developer #

docker compose up --build

Alur kerja:

  • Edit kode → auto rebuild
  • Error langsung muncul
  • Database siap pakai

Anti-Pattern #

❌ Multi-stage build untuk local dev ❌ Tidak cache Cargo registry ❌ Copy seluruh source sebelum dependency ❌ Tidak set ROCKET_ADDRESS


Dockerfile Production Terpisah? #

Saat:

  • Deploy ke Kubernetes
  • CI/CD pipeline
  • Image size penting
  • Security hardening

Solusi:

  • Dockerfile.dev
  • Dockerfile.prod

Penutup #

Docker untuk Rocket bukan sekadar menjalankan Rust di container, tetapi tentang:

  • Mengurangi compile cost Rust
  • Menjaga DX tetap cepat
  • Menyatukan environment seluruh tim

Dengan Dockerfile dan Docker Compose ini, Anda mendapatkan local development Rocket yang stabil, cepat, dan scalable.

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact