# syntax=docker/dockerfile:1.6
ARG RUST_VERSION=1.91
ARG RUST_IMAGE=rust:${RUST_VERSION}-slim-bookworm
ARG APP_NAME=constellate
FROM --platform=$BUILDPLATFORM ${RUST_IMAGE} AS build
ARG APP_NAME=constellate
WORKDIR /app
# Prefer sparse protocol for faster and cache-friendly dependency downloads.
ENV CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse \
CARGO_TERM_COLOR=always \
APP_NAME=${APP_NAME}
# Prebuild dependencies to take advantage of Docker layer caching.
COPY Cargo.toml Cargo.lock build.rs ./
RUN mkdir src \
&& echo 'fn main() {}' > src/main.rs \
&& cargo build --locked --release \
&& rm -rf src
COPY . .
# Touch the primary entrypoint so Cargo notices real sources even if their
# timestamps are older than the stubbed file from the dependency warmup layer.
RUN touch src/main.rs \
&& cargo build --locked --release --bin "${APP_NAME}"
FROM debian:bookworm-slim AS runtime
ARG APP_NAME=constellate
ARG APP_USER=constellate
ARG APP_HOME=/srv/${APP_NAME}
ARG WORKSPACE_DIR=/workspace
ARG BUILD_DATE="unknown"
ARG VCS_REF="unknown"
ARG VERSION="dev"
LABEL org.opencontainers.image.title="Constellate" \
org.opencontainers.image.description="A Rust CLI that turns curated markdown collections into a static, themeable knowledge portal." \
org.opencontainers.image.url="https://github.com/onjin/constellate" \
org.opencontainers.image.source="https://github.com/onjin/constellate" \
org.opencontainers.image.vendor="Constellate" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${VCS_REF}" \
org.opencontainers.image.created="${BUILD_DATE}"
# Install only the runtime essentials and clean up apt metadata to keep the image small.
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates tini \
&& rm -rf /var/lib/apt/lists/*
RUN groupadd --system ${APP_USER} \
&& useradd --system --create-home --home-dir ${APP_HOME} --gid ${APP_USER} --shell /usr/sbin/nologin ${APP_USER} \
&& mkdir -p ${WORKSPACE_DIR}
WORKDIR /
COPY --from=build /app/target/release/${APP_NAME} /usr/local/bin/${APP_NAME}
RUN chown -R ${APP_USER}:${APP_USER} ${APP_HOME} ${WORKSPACE_DIR}
VOLUME ["${WORKSPACE_DIR}"]
USER ${APP_USER}
EXPOSE 8080
ENTRYPOINT ["/usr/bin/tini", "--", "constellate"]
CMD ["serve", "--input", "/workspace", "--output", "/workspace/dist", "--host", "0.0.0.0", "-p", "8080"]