Files
Lucas RayanandClaude Opus 5 64c9efe078 #21: keep devDependencies in the build stage regardless of NODE_ENV
The deployment sets NODE_ENV=production, and npm omits devDependencies
when it is set - so "npm ci" in the build stage installed no typescript
and "npm run build" failed with exit 127, command not found. The first
Coolify deployment died there.

The build stage now asks for them explicitly rather than depending on the
environment it happens to run in. Reproduced by building all three images
with NODE_ENV=production before and after.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 14:08:09 -03:00

34 lines
1.4 KiB
Docker

FROM node:20-alpine AS build
WORKDIR /app
COPY package.json package-lock.json* ./
# --include=dev: the Next build needs devDependencies, and npm omits them
# when NODE_ENV=production, which the deployment sets.
RUN npm ci --include=dev
COPY . .
RUN npm run build
FROM node:20-alpine
# The node:20-alpine tag lags its Alpine base, so pending security patches
# (openssl, busybox) land only with an explicit upgrade.
RUN apk upgrade --no-cache \
# The runtime only ever runs "node"; npm is not invoked and its own
# bundled dependency tree (sigstore, cross-spawn, glob, ...) is what
# every remaining image CVE came from. Removing it drops the whole
# class instead of chasing each advisory.
&& rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx
WORKDIR /app
# --chown matters here: Next's standalone server writes its cache under
# .next at runtime, which it cannot do if the tree belongs to root.
COPY --from=build --chown=node:node /app/.next/standalone ./
COPY --from=build --chown=node:node /app/.next/static ./.next/static
COPY --from=build --chown=node:node /app/public ./public
# The node images ship an unprivileged "node" user (uid 1000).
USER node
EXPOSE 3000
# Docker sets HOSTNAME to the container ID by default; Next's standalone
# server.js honors that env var and binds only to it, refusing localhost
# (and thus the healthcheck). Force it to listen on every interface.
ENV HOSTNAME=0.0.0.0
CMD ["node", "server.js"]