# pds.js as a single container.
#
# Built from workspace source rather than from the published packages, so the
# image always matches the commit it was built from and can be built before a
# release reaches npm.

FROM node:22-slim AS builder
# corepack resolves the pnpm version from package.json's packageManager field,
# and prompts before downloading it — which would hang a non-interactive build.
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
RUN corepack enable
WORKDIR /app

# better-sqlite3 publishes prebuilds for common platforms, but falls back to
# compiling from source when there is no match for the target.
RUN apt-get update \
  && apt-get install -y --no-install-recommends python3 make g++ \
  && rm -rf /var/lib/apt/lists/*

# Manifests first, so dependency resolution caches independently of source
# edits. pnpm checks the whole workspace against the lockfile, so every
# member's manifest has to be present even though most go unused here.
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
COPY docker/package.json                    docker/
COPY packages/blobs-deno/package.json       packages/blobs-deno/
COPY packages/blobs-fs/package.json         packages/blobs-fs/
COPY packages/blobs-s3/package.json         packages/blobs-s3/
COPY packages/cloudflare/package.json       packages/cloudflare/
COPY packages/core/package.json             packages/core/
COPY packages/deno/package.json             packages/deno/
COPY packages/lexicon-resolver/package.json packages/lexicon-resolver/
COPY packages/node/package.json             packages/node/
COPY packages/readonly/package.json         packages/readonly/
COPY packages/spaces/package.json           packages/spaces/
COPY packages/storage-sqlite/package.json   packages/storage-sqlite/
COPY examples/cloudflare/package.json       examples/cloudflare/
COPY examples/deno/package.json             examples/deno/
COPY examples/node/package.json             examples/node/
COPY examples/runclub/package.json          examples/runclub/

# better-sqlite3 needs its install script to run. The repo allows that in
# .npmrc, but that file is also where npm auth tokens live, so it is passed
# explicitly here rather than copied into a layer.
RUN printf 'only-built-dependencies[]=better-sqlite3\n' > .npmrc \
  && pnpm install --frozen-lockfile --prod --filter pds-container...

# Source last: editing it invalidates only this layer.
COPY packages packages
COPY docker/server.js docker/

FROM node:22-slim AS runtime
WORKDIR /app

# Runs unprivileged. node:22-slim ships a "node" user for exactly this.
RUN mkdir -p /data && chown node:node /data
USER node

COPY --from=builder --chown=node:node /app /app

ENV NODE_ENV=production
ENV PDS_DB_PATH=/data/pds.db
ENV PDS_BLOBS_DIR=/data/blobs
ENV PORT=3000

# PDS_HOSTNAME and JWT_SECRET are deliberately unset — the entrypoint exits
# rather than inventing values for them.
VOLUME /data
EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||3000)+'/xrpc/_health').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"

CMD ["node", "docker/server.js"]
