armature-framework 0.3.0

A modern, type-safe HTTP framework for Rust inspired by Angular and NestJS. Features dependency injection, decorators, middleware, authentication (JWT/OAuth2/SAML), validation, OpenAPI/Swagger, caching, job queues, and observability.
# Armature API Dockerfile with Metrics Support
# Multi-stage build for minimal image size

# The chef/planner boilerplate below (Stages 1-2) is intentionally duplicated
# across all 4 Armature Dockerfiles rather than extracted into a shared base
# image, since this repo builds each with plain `docker build` (no buildx
# bake infra). Keep RUST_VERSION / CARGO_CHEF_VERSION in sync across:
#   docker/full-stack/Dockerfile
#   docker/microservices/Dockerfile.service
#   docker/microservices/Dockerfile.worker
#   docker/observability/Dockerfile.api
ARG RUST_VERSION=1.94.1
# Pinned to a specific cargo-chef release (not "latest") for reproducible
# builds. Update periodically: https://github.com/LukeMathWalker/cargo-chef/releases
ARG CARGO_CHEF_VERSION=0.1.68

# ==================================================
# Stage 1: Chef - base image with cargo-chef installed
# ==================================================
FROM lukemathwalker/cargo-chef:${CARGO_CHEF_VERSION}-rust-${RUST_VERSION}-alpine AS chef
WORKDIR /app

# ==================================================
# Stage 2: Planner - compute the dependency-only recipe
# ==================================================
FROM chef AS planner

# The whole workspace (all Cargo.toml manifests + sources) is required for
# `cargo chef prepare` to resolve the dependency graph, but this stage only
# ever produces recipe.json, which is all that gets copied forward.
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

# ==================================================
# Stage 3: Build
# ==================================================
FROM chef AS builder

WORKDIR /app

# Install build dependencies
RUN apk add --no-cache musl-dev openssl-dev openssl-libs-static pkgconfig

# Build dependencies only. This layer is cache-keyed on recipe.json (which is
# itself derived only from Cargo.toml/Cargo.lock), so it is skipped entirely
# on rebuilds that only change application source.
COPY --from=planner /app/recipe.json recipe.json
# Scoped to the single example this image actually builds (metrics_example)
# instead of --examples, so the cached dependency layer isn't inflated by
# every other example in the workspace.
RUN cargo chef cook --release --example metrics_example --recipe-path recipe.json

# Copy actual source
COPY . .

# Build the metrics server example
RUN cargo build --release --example metrics_example && \
    strip /app/target/release/examples/metrics_example

# Runtime stage
FROM alpine:3.19

WORKDIR /app

# Install runtime dependencies
RUN apk add --no-cache ca-certificates curl

# Copy binary
COPY --from=builder /app/target/release/examples/metrics_example /app/server

# Create non-root user
RUN adduser -D -u 1000 armature
USER armature

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:3000/health || exit 1

ENTRYPOINT ["/app/server"]