armature-framework 0.4.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 Worker Service Dockerfile
# Background job processing service

# 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

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 (cqrs_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 cqrs_example --recipe-path recipe.json

COPY . .

# Build worker (use actual worker binary)
RUN cargo build --release --example cqrs_example && \
    strip /app/target/release/examples/cqrs_example

# Runtime stage
FROM alpine:3.19

WORKDIR /app

RUN apk add --no-cache ca-certificates && \
    adduser -D -u 1000 armature

COPY --from=builder /app/target/release/examples/cqrs_example /app/worker

USER armature

# Workers don't need to expose ports
# EXPOSE 3000

# No HTTP health check for workers - rely on process health
HEALTHCHECK --interval=60s --timeout=10s --start-period=10s --retries=3 \
    CMD ps aux | grep worker || exit 1

ENTRYPOINT ["/app/worker"]