# Multi-stage Dockerfile for Paladin
# Optimized for production deployment with minimal image size
# Supports multi-architecture builds (amd64, arm64)
# =============================================================================
# Stage 1: Build Dependencies (Chef)
# Caches Rust dependencies separately from application code
# Note: Using Bookworm (Debian 12) for OpenSSL 3.x support
# =============================================================================
FROM rust:1.93-slim-bookworm AS chef
WORKDIR /app
# Install cargo-chef for dependency caching (pinned for reproducible builds)
RUN cargo install cargo-chef --version 0.1.77 --locked
# =============================================================================
# Stage 2: Prepare Recipe (Planner)
# Analyzes the project and generates a recipe for dependencies
# =============================================================================
FROM chef AS planner
# Copy manifests first (changes rarely) to maximise layer cache reuse.
# Each crate Cargo.toml is copied individually so the recipe layer only
# invalidates when a manifest — not source — changes.
COPY Cargo.toml Cargo.lock ./
COPY crates/paladin-core/Cargo.toml crates/paladin-core/Cargo.toml
COPY crates/paladin-ports/Cargo.toml crates/paladin-ports/Cargo.toml
COPY crates/paladin-battalion/Cargo.toml crates/paladin-battalion/Cargo.toml
COPY crates/paladin-llm/Cargo.toml crates/paladin-llm/Cargo.toml
COPY crates/paladin-memory/Cargo.toml crates/paladin-memory/Cargo.toml
COPY crates/paladin-storage/Cargo.toml crates/paladin-storage/Cargo.toml
COPY crates/paladin-notifications/Cargo.toml crates/paladin-notifications/Cargo.toml
COPY crates/paladin-content/Cargo.toml crates/paladin-content/Cargo.toml
COPY crates/paladin-web/Cargo.toml crates/paladin-web/Cargo.toml
# Copy source trees so cargo-chef can resolve workspace member paths
COPY src ./src
COPY crates ./crates
COPY benches ./benches
RUN cargo chef prepare --recipe-path recipe.json
# =============================================================================
# Stage 3: Build Dependencies (Builder)
# Builds dependencies using the recipe (cached layer)
# =============================================================================
FROM chef AS builder
# Install system dependencies needed for build
RUN apt-get update && apt-get install -y \
pkg-config \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
# Copy the recipe and build dependencies
COPY --from=planner /app/recipe.json recipe.json
# --workspace ensures all crate dependencies are pre-built and cached
RUN cargo chef cook --release --workspace --recipe-path recipe.json
# =============================================================================
# Stage 4: Build Application
# Builds the actual application code
# =============================================================================
FROM builder AS app-builder
WORKDIR /app
# Copy application source
COPY Cargo.toml Cargo.lock ./
COPY src ./src
COPY crates ./crates
COPY benches ./benches
COPY migrations ./migrations
# Note: config.yml is NOT baked into the image; provide at runtime via volume mount.
# Build the application in release mode
# Dependencies are already cached from the chef cook stage
RUN cargo build --release --workspace --bin paladin
# Strip debug symbols to reduce binary size
RUN strip target/release/paladin
# =============================================================================
# Stage 5: Runtime (Distroless)
# Minimal runtime image with only essential components
# =============================================================================
FROM gcr.io/distroless/cc-debian12:latest
# Metadata
LABEL org.opencontainers.image.title="Paladin"
LABEL org.opencontainers.image.description="Enterprise AI orchestration framework with multi-agent coordination"
LABEL org.opencontainers.image.version="0.1.0"
LABEL org.opencontainers.image.authors="Am0rfu5"
LABEL org.opencontainers.image.source="https://github.com/DF3NDR/paladin-dev-env"
LABEL org.opencontainers.image.licenses="MIT"
# Copy binary from builder
COPY --from=app-builder /app/target/release/paladin /usr/local/bin/paladin
# Note: config.yml must be provided at runtime via a volume mount or ConfigMap.
# Example: docker run -v /path/to/config.yml:/etc/paladin/config.yml paladin:latest
# Copy migrations (if needed at runtime)
COPY --from=app-builder /app/migrations /etc/paladin/migrations
# Set working directory
WORKDIR /app
# Expose default port (adjust based on your application)
EXPOSE 8080
# Run as non-root user (distroless provides this)
# USER nonroot:nonroot
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD ["/usr/local/bin/paladin", "health"]
# Run the application
ENTRYPOINT ["/usr/local/bin/paladin"]
CMD ["run"]