# syntax=docker/dockerfile:1 # # Vinterliste — single-image container. # Build stage compiles the frontend with Vite; runtime image runs Bun. ARG BUN_VERSION=1.3 ARG BUILD_DATE ARG GIT_REVISION # ---- Builder --------------------------------------------------------------- FROM docker.io/oven/bun:${BUN_VERSION} AS builder WORKDIR /app # Install dependencies first so they cache independently of source. COPY package.json bun.lockb* ./ RUN bun install --frozen-lockfile || bun install # Copy the rest of the source and build the frontend bundle. COPY tsconfig.json ./ COPY shared ./shared COPY server ./server COPY frontend ./frontend RUN bun run build:frontend # ---- Runtime --------------------------------------------------------------- FROM docker.io/oven/bun:${BUN_VERSION}-slim WORKDIR /app ARG BUILD_DATE ARG GIT_REVISION # OCI labels keep the image traceable even when tagged :latest. LABEL org.opencontainers.image.title="vinterliste" \ org.opencontainers.image.description="End-to-end encrypted winter activity list" \ org.opencontainers.image.source="https://example.invalid/vinterliste" \ org.opencontainers.image.created="${BUILD_DATE}" \ org.opencontainers.image.revision="${GIT_REVISION}" # Bake the same info into /etc/build-info so a running container can report it. RUN printf 'build_date=%s\ngit_revision=%s\n' "${BUILD_DATE:-unknown}" "${GIT_REVISION:-unknown}" > /etc/build-info # Copy production artefacts only. node_modules is reproducible from package.json, # but we install fresh to keep the runtime image small and unambiguous. COPY package.json bun.lockb* ./ RUN bun install --frozen-lockfile --production || bun install --production COPY --from=builder /app/shared ./shared COPY --from=builder /app/server ./server COPY --from=builder /app/frontend/dist ./frontend/dist # SQLite WAL files live in /app/data, which is the documented mount point. RUN mkdir -p /app/data && chown -R bun:bun /app/data VOLUME /app/data ENV NODE_ENV=production \ PORT=3000 \ VINTERLISTE_DB=/app/data/vinterliste.db \ BUILD_DATE=${BUILD_DATE} \ GIT_REVISION=${GIT_REVISION} EXPOSE 3000 USER bun HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD bun -e "fetch('http://localhost:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" CMD ["bun", "run", "server/index.ts"]