- Create the runtime write targets (/app/storage, /app/public/nitro-assets, /app/public/swf, /var/www/Gamedata) owned by UID/GID 33 in the runner image so running without the bound volumes no longer hits ENOENT. - Bake a HEALTHCHECK into the image so `docker run` (ci-deploy.sh) also reports Docker-level health; compose can still override it with its own probe. - Add the dockerfile:1 syntax pragma and ignore non-pnpm lockfiles so a stray package-lock.json/yarn.lock can never taint the build context.
48 lines
2.4 KiB
Docker
48 lines
2.4 KiB
Docker
# syntax=docker/dockerfile:1
|
|
# node:alpine = latest Node within the supported LTS major (tracks the newest
|
|
# patch automatically; currently v26.x, which satisfies package.json's
|
|
# engines ">=26.8.1 <27").
|
|
FROM node:alpine AS builder
|
|
WORKDIR /app
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
# Real release id supplied by CI (ci-deploy.sh) so next.config.ts skips git
|
|
# entirely (there is no .git in the build context). Defaults to "unknown".
|
|
ARG NEXT_DEPLOYMENT_ID="unknown"
|
|
ENV NEXT_DEPLOYMENT_ID="$NEXT_DEPLOYMENT_ID"
|
|
# pnpm install is always pinned to the version in package.json's
|
|
# `packageManager` field (pnpm auto-selects it on install), so this global
|
|
# install only needs to exist as a bootstrap and follows the active major.
|
|
RUN apk add --no-cache git \
|
|
&& npm install -g pnpm@latest
|
|
# pnpm-workspace.yaml + .npmrc must be present too: the lockfile records the
|
|
# overrides from pnpm-workspace.yaml, and --frozen-lockfile rejects a build
|
|
# where the workspace config is absent (ERR_PNPM_LOCKFILE_CONFIG_MISMATCH).
|
|
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml* .npmrc* ./
|
|
# pnpm fetch: download all deps into $PNPM_STORE first, so only the lockfile
|
|
# change (not source changes) invalidates the network-heavy download layer.
|
|
RUN pnpm fetch --ignore-scripts
|
|
RUN pnpm install --frozen-lockfile --ignore-scripts --offline
|
|
COPY . .
|
|
RUN pnpm run build
|
|
|
|
FROM node:alpine AS runner
|
|
WORKDIR /app
|
|
ENV NODE_ENV=production \
|
|
NEXT_TELEMETRY_DISABLED=1 \
|
|
PORT=3002 \
|
|
HOSTNAME=0.0.0.0
|
|
RUN apk add --no-cache tini \
|
|
&& addgroup -g 33 -S nextjs && adduser -u 33 -S -G nextjs nextjs \
|
|
&& mkdir -p /app/storage /app/public/nitro-assets /app/public/swf /var/www/Gamedata \
|
|
&& chown -R 33:33 /app/storage /app/public /var/www/Gamedata
|
|
COPY --from=builder --chown=nextjs:nextjs /app/public ./public
|
|
COPY --from=builder --chown=nextjs:nextjs /app/.next/standalone ./
|
|
COPY --from=builder --chown=nextjs:nextjs /app/.next/static ./.next/static
|
|
USER nextjs
|
|
EXPOSE 3002
|
|
# Self-contained healthcheck so `docker run` (ci-deploy) also gets Docker-level
|
|
# health; docker-compose overrides this with its own probe if needed.
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
|
CMD ["node", "-e", "fetch('http://127.0.0.1:'+(process.env.PORT||'3002')+'/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
|
ENTRYPOINT ["/sbin/tini", "--"]
|
|
CMD ["node", "server.js"] |