Dockerfile
Rama main · réplica de lectura del repositorio original.
### Build stage ##############################################################
FROM node:20-alpine AS builder
WORKDIR /app
# better-sqlite3 needs a C++ toolchain to compile its native binding.
# python3 is required by node-gyp, the build orchestrator.
RUN apk add --no-cache python3 make g++
COPY package.json package-lock.json ./
RUN npm ci --no-audit --no-fund
COPY tsconfig.json ./
COPY src ./src
RUN npm run build
# Strip dev deps so the prod node_modules we copy below is small.
RUN npm prune --omit=dev
### Runtime stage ############################################################
FROM node:20-alpine AS runtime
# docker-cli + the compose v2 plugin so the daemon can shell out to
# `docker compose` against the host's mounted /var/run/docker.sock.
# tini gives us proper signal forwarding on SIGINT/SIGTERM.
# tzdata so $TZ is honored — the v0.4.3 daily-digest scheduler uses local
# wall-clock hour for its fire decision, and without tzdata Alpine treats
# any TZ as UTC.
# git: optional, for BUMPSIGHT_GIT_COMMIT — commits the rewritten compose when
# the target stack dir is a git working copy. No-op when the feature is off.
# python3: so a stack repo's Python pre-commit hook (e.g. a leak guard) can run
# on bumpsight's commits instead of failing them with "can't execute python3".
RUN apk add --no-cache docker-cli docker-cli-compose tini tzdata git python3
ENV NODE_ENV=production
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./
COPY README.md CHANGELOG.md LICENSE ./
# Persistent state mount: the SQLite file lives here.
VOLUME ["/var/lib/bumpsight"]
# Approve / deny links + healthcheck endpoint.
EXPOSE 9100
ENTRYPOINT ["/sbin/tini", "--", "node", "/app/dist/cli.js"]
CMD ["daemon"]