# --- Build stage --- FROM rust:1.88-alpine AS builder RUN apk add --no-cache musl-dev pkgconfig openssl-dev WORKDIR /app COPY Cargo.toml Cargo.lock* ./ # Pre-fetch deps with a dummy build for layer caching RUN mkdir src && echo "fn main(){}" > src/main.rs && \ cargo build --release && \ rm -rf src COPY src ./src COPY static ./static COPY migrations ./migrations RUN touch src/main.rs && cargo build --release # --- Runtime stage --- FROM alpine:3.21 RUN apk add --no-cache ca-certificates ffmpeg # Run as a non-root user. Pre-create and chown the media + export mount paths so # the fresh named volumes inherit the non-root ownership (Docker seeds an empty # named volume from the image directory, preserving its uid/gid) and uploads + # export archives can be written. Exports live OUTSIDE /media on purpose so the # public media ServeDir can't reach them. RUN addgroup -S app && adduser -S app -G app WORKDIR /app COPY --from=builder /app/target/release/eventsnap-backend ./ RUN mkdir -p /media /exports && chown -R app:app /app /media /exports USER app EXPOSE 3000 CMD ["./eventsnap-backend"]