# syntax=docker/dockerfile:1.7
# =============================================================================
# AllSource Core - Production-Optimized Multi-Stage Dockerfile
# Optimized for: Fast cold starts, minimal image size, security
#
# Build targets (community edition — open source, Apache 2.0):
# docker build --target runtime-community . # Distroless, community features
# docker build --target runtime-community-alpine . # Alpine + HEALTHCHECK
#
# Build targets (enterprise edition — BSL 1.1):
# docker build --target runtime . # Distroless, all features (default)
# docker build --target runtime-alpine . # Alpine + HEALTHCHECK
# =============================================================================
ARG RUST_VERSION=1.92
ARG ALPINE_VERSION=3.23
ARG EDITION=enterprise
# =============================================================================
# Stage 1: Chef - Prepare cargo-chef for dependency caching
# =============================================================================
FROM rust:${RUST_VERSION}-alpine AS chef
RUN apk add --no-cache musl-dev && \
cargo install cargo-chef --locked
WORKDIR /app
# =============================================================================
# Stage 2: Planner - Analyze dependencies
# =============================================================================
FROM chef AS planner
# Copy workspace root manifests first
COPY Cargo.toml Cargo.lock ./
# Copy the core app source
COPY apps/core/Cargo.toml apps/core/Cargo.lock* apps/core/
COPY apps/core/src apps/core/src
# Create stubs for workspace members and optional targets
# Only workspace.members need stubs — excluded crates (registry, better-auth-allsource)
# have their own Cargo.toml and are invisible to the workspace resolver.
COPY tooling/performance/Cargo.toml tooling/performance/Cargo.toml
COPY sdks/rust/Cargo.toml sdks/rust/Cargo.toml
# core_nif is a cdylib (Rustler NIF) which musl cannot produce, so we stub it
# as a plain lib to satisfy workspace resolution without triggering cdylib builds
RUN mkdir -p tooling/performance/src sdks/rust/src \
apps/mcp-server-elixir/native/core_nif/src \
apps/core/benches apps/core/tests/stress_tests && \
echo 'fn main() {}' > tooling/performance/src/main.rs && \
echo '' > sdks/rust/src/lib.rs && \
printf '[package]\nname = "core_nif"\nversion = "0.1.0"\nedition = "2021"\n\n[lib]\nname = "core_nif"\npath = "src/lib.rs"\n\n[dependencies]\n' \
> apps/mcp-server-elixir/native/core_nif/Cargo.toml && \
echo '' > apps/mcp-server-elixir/native/core_nif/src/lib.rs && \
echo 'fn main() {}' > apps/core/benches/performance_benchmarks.rs && \
echo 'fn main() {}' > apps/core/tests/stress_tests/seven_day_stress.rs && \
cargo chef prepare --recipe-path recipe.json
# =============================================================================
# Stage 3: Builder base - Shared dependency cooking
# =============================================================================
FROM chef AS builder-base
ARG VERSION=dev
ARG REVISION=unknown
ARG BUILDTIME=unknown
# Cook dependencies from recipe (cached layer — recipe is version-agnostic)
# cargo-chef replaces version fields with placeholders, so version bumps in
# Cargo.toml/Cargo.lock don't invalidate this expensive layer.
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json -p allsource-core --features analytics
# Now copy real manifests (version-sensitive) and set up workspace structure
COPY Cargo.toml Cargo.lock ./
COPY apps/core/Cargo.toml apps/core/
COPY tooling/performance/Cargo.toml tooling/performance/
COPY sdks/rust/Cargo.toml sdks/rust/
RUN mkdir -p apps/core/src tooling/performance/src sdks/rust/src \
apps/mcp-server-elixir/native/core_nif/src && \
echo 'fn main() {}' > apps/core/src/main.rs && \
echo 'fn main() {}' > tooling/performance/src/main.rs && \
echo '' > sdks/rust/src/lib.rs && \
printf '[package]\nname = "core_nif"\nversion = "0.1.0"\nedition = "2021"\n\n[lib]\nname = "core_nif"\npath = "src/lib.rs"\n\n[dependencies]\n' \
> apps/mcp-server-elixir/native/core_nif/Cargo.toml && \
echo '' > apps/mcp-server-elixir/native/core_nif/src/lib.rs
# Copy actual source files for binary build
COPY apps/core/src apps/core/src
RUN mkdir -p apps/core/benches apps/core/tests/stress_tests && \
echo 'fn main() {}' > apps/core/benches/performance_benchmarks.rs && \
echo 'fn main() {}' > apps/core/tests/stress_tests/seven_day_stress.rs
# =============================================================================
# Stage 3a: Builder Community - Community edition (Apache 2.0)
# =============================================================================
FROM builder-base AS builder-community
RUN CARGO_BUILD_JOBS=4 cargo build --release -p allsource-core --bin allsource-core --features community,analytics && \
strip /app/target/release/allsource-core
# =============================================================================
# Stage 3b: Builder Enterprise - Enterprise edition (BSL 1.1)
# =============================================================================
FROM builder-base AS builder-enterprise
RUN CARGO_BUILD_JOBS=4 cargo build --release -p allsource-core --bin allsource-core --features enterprise,analytics && \
strip /app/target/release/allsource-core
# =============================================================================
# Stage 4a: Runtime Community - Distroless (Apache 2.0, open source)
# =============================================================================
FROM gcr.io/distroless/static-debian12:nonroot AS runtime-community
ARG VERSION=dev
ARG REVISION=unknown
ARG BUILDTIME=unknown
LABEL org.opencontainers.image.title="AllSource Core (Community)" \
org.opencontainers.image.description="High-performance event store built in Rust — community edition" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${REVISION}" \
org.opencontainers.image.created="${BUILDTIME}" \
org.opencontainers.image.vendor="AllSource Team" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.source="https://github.com/all-source-os/allsource-monorepo" \
org.opencontainers.image.base.name="gcr.io/distroless/static-debian12:nonroot"
WORKDIR /app
COPY --from=builder-community /app/target/release/allsource-core ./allsource-core
EXPOSE 3900
ENV RUST_LOG=allsource_core=info,tower_http=info \
ALLSOURCE_HOST=0.0.0.0 \
ALLSOURCE_PORT=3900 \
ALLSOURCE_DATA_DIR=/app/data \
PORT=3900 \
MALLOC_ARENA_MAX=2
ENTRYPOINT ["./allsource-core"]
# =============================================================================
# Stage 4b: Runtime Enterprise (DEFAULT) - Distroless (BSL 1.1)
# =============================================================================
FROM gcr.io/distroless/static-debian12:nonroot AS runtime
ARG VERSION=dev
ARG REVISION=unknown
ARG BUILDTIME=unknown
LABEL org.opencontainers.image.title="AllSource Core (Enterprise)" \
org.opencontainers.image.description="High-performance event store built in Rust — enterprise edition" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${REVISION}" \
org.opencontainers.image.created="${BUILDTIME}" \
org.opencontainers.image.vendor="AllSource Team" \
org.opencontainers.image.licenses="BSL-1.1" \
org.opencontainers.image.source="https://github.com/all-source-os/allsource-monorepo" \
org.opencontainers.image.base.name="gcr.io/distroless/static-debian12:nonroot"
WORKDIR /app
COPY --from=builder-enterprise /app/target/release/allsource-core ./allsource-core
EXPOSE 3900
ENV RUST_LOG=allsource_core=info,tower_http=info \
ALLSOURCE_HOST=0.0.0.0 \
ALLSOURCE_PORT=3900 \
ALLSOURCE_DATA_DIR=/app/data \
PORT=3900 \
MALLOC_ARENA_MAX=2
ENTRYPOINT ["./allsource-core"]
# =============================================================================
# Stage 4c: Runtime Community Alpine - With Docker HEALTHCHECK
# =============================================================================
FROM alpine:${ALPINE_VERSION} AS runtime-community-alpine
ARG VERSION=dev
ARG REVISION=unknown
ARG BUILDTIME=unknown
LABEL org.opencontainers.image.title="AllSource Core (Community)" \
org.opencontainers.image.description="High-performance event store built in Rust — community edition" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${REVISION}" \
org.opencontainers.image.created="${BUILDTIME}" \
org.opencontainers.image.vendor="AllSource Team" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.source="https://github.com/all-source-os/allsource-monorepo" \
org.opencontainers.image.base.name="alpine:${ALPINE_VERSION}"
RUN apk add --no-cache curl ca-certificates && \
addgroup -g 1000 -S allsource && \
adduser -u 1000 -S allsource -G allsource -h /app -s /sbin/nologin && \
mkdir -p /app/data && \
chown -R allsource:allsource /app
WORKDIR /app
COPY --from=builder-community --chown=allsource:allsource /app/target/release/allsource-core ./allsource-core
USER allsource
EXPOSE 3900
ENV RUST_LOG=allsource_core=info,tower_http=info \
ALLSOURCE_HOST=0.0.0.0 \
ALLSOURCE_PORT=3900 \
ALLSOURCE_DATA_DIR=/app/data \
PORT=3900 \
MALLOC_ARENA_MAX=2
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3900/health || exit 1
ENTRYPOINT ["./allsource-core"]
# =============================================================================
# Stage 4d: Runtime Enterprise Alpine - With Docker HEALTHCHECK
# =============================================================================
FROM alpine:${ALPINE_VERSION} AS runtime-alpine
ARG VERSION=dev
ARG REVISION=unknown
ARG BUILDTIME=unknown
LABEL org.opencontainers.image.title="AllSource Core (Enterprise)" \
org.opencontainers.image.description="High-performance event store built in Rust — enterprise edition" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${REVISION}" \
org.opencontainers.image.created="${BUILDTIME}" \
org.opencontainers.image.vendor="AllSource Team" \
org.opencontainers.image.licenses="BSL-1.1" \
org.opencontainers.image.source="https://github.com/all-source-os/allsource-monorepo" \
org.opencontainers.image.base.name="alpine:${ALPINE_VERSION}"
RUN apk add --no-cache curl ca-certificates && \
addgroup -g 1000 -S allsource && \
adduser -u 1000 -S allsource -G allsource -h /app -s /sbin/nologin && \
mkdir -p /app/data && \
chown -R allsource:allsource /app
WORKDIR /app
COPY --from=builder-enterprise --chown=allsource:allsource /app/target/release/allsource-core ./allsource-core
USER allsource
EXPOSE 3900
ENV RUST_LOG=allsource_core=info,tower_http=info \
ALLSOURCE_HOST=0.0.0.0 \
ALLSOURCE_PORT=3900 \
ALLSOURCE_DATA_DIR=/app/data \
PORT=3900 \
MALLOC_ARENA_MAX=2
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3900/health || exit 1
ENTRYPOINT ["./allsource-core"]