Files
pn-new-crm/Dockerfile.worker
Matt f74448c287
Some checks failed
Build & Push Docker Images / lint (push) Successful in 1m27s
Build & Push Docker Images / build-and-push (push) Failing after 8m24s
fix(docker): skip husky install in worker runner stage
`pnpm install --frozen-lockfile --prod` runs the package.json `prepare`
script (`husky`) but in --prod mode husky (a devDependency) isn't
installed → "sh: husky: not found" → install fails → Docker build dies.

`ENV HUSKY=0` is husky 9+'s official skip mechanism for CI/Docker
contexts. Adding it before the prod install in Dockerfile.worker.

The main Dockerfile is unaffected because its runner stage copies the
prebuilt `.next/standalone` rather than running pnpm install.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:57:41 +02:00

46 lines
2.2 KiB
Docker

# Stage 1: Install dependencies (dev deps needed for esbuild)
FROM node:20-alpine AS deps
RUN corepack enable && corepack prepare pnpm@10.33.2 --activate
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod=false
# Stage 2: Build the worker bundle
FROM node:20-alpine AS builder
RUN corepack enable && corepack prepare pnpm@10.33.2 --activate
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV SKIP_ENV_VALIDATION=1
RUN pnpm build:worker
# Stage 3: Production runner (prod deps only).
#
# Critical ordering: create the worker user FIRST and chown the workdir
# BEFORE pnpm install, so node_modules + lazy-cache directories
# (tesseract.js, sharp) are owned by the worker user. Without this, the
# previous layout had pnpm install run as root → node_modules root-owned
# → tesseract.js / sharp wrote to node_modules/.cache and EACCES'd at
# first PDF parse in prod (auditor-K §39).
FROM node:20-alpine AS runner
RUN corepack enable && corepack prepare pnpm@10.33.2 --activate
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 worker
WORKDIR /app
RUN chown -R worker:nodejs /app
USER worker
COPY --chown=worker:nodejs package.json pnpm-lock.yaml ./
# HUSKY=0 skips the husky install during the `prepare` script — husky is a
# dev dependency so it's not present in --prod installs, and without this
# guard pnpm install fails with "sh: husky: not found" (husky 9+ honors
# the HUSKY=0 env var as the official CI/Docker skip mechanism).
ENV HUSKY=0
RUN pnpm install --frozen-lockfile --prod
COPY --from=builder --chown=worker:nodejs /app/dist/worker.js ./worker.js
# Healthcheck — pings Redis from inside the worker container. Without
# this, a worker whose Redis connection has silently dropped (BullMQ
# rejects new jobs but the Node process is alive) is invisible to
# compose / swarm and jobs queue indefinitely (auditor-K §40).
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD node -e "const Redis=require('ioredis');const r=new Redis(process.env.REDIS_URL,{maxRetriesPerRequest:1,connectTimeout:3000,lazyConnect:true});r.connect().then(()=>r.ping()).then(()=>{r.disconnect();process.exit(0)}).catch(()=>process.exit(1))" || exit 1
CMD ["node", "worker.js"]