gendesign/tradein-mvp/frontend/Dockerfile
bot-backend 4e8cf5ab62
All checks were successful
CI Trade-In / changes (pull_request) Successful in 11s
CI / changes (pull_request) Successful in 13s
CI Trade-In / browser-tests (pull_request) Successful in 1m16s
CI Trade-In / frontend-checks (pull_request) Successful in 1m30s
CI / frontend-tests (pull_request) Successful in 1m23s
CI / openapi-codegen-check (pull_request) Successful in 2m23s
CI Trade-In / backend-tests (pull_request) Successful in 5m47s
CI / backend-tests (pull_request) Successful in 18m12s
chore(ci): node 20 отслужил — рантайм фронтов и оба CI-джоба на node 24 LTS
Node 20 вышел из поддержки 30.04.2026: security-патчи для него больше не
выпускаются, а образ node:20-alpine продолжает собираться и молча уносить это
в прод. Node 24 — текущая Active LTS.

Меняется ровно major рантайма, больше ничего:
  frontend/Dockerfile             node:20-alpine → node:24-alpine (deps/builder/runner)
  tradein-mvp/frontend/Dockerfile то же, три стадии
  .forgejo/workflows/ci.yml       node-version "20" → "24" (два джоба)
  .forgejo/workflows/ci-tradein.yml то же (один джоб)

Версия в CI намеренно держится равной major'у из Dockerfile — так было и
раньше, комментарии рядом обновлены вместе с числом, чтобы не разошлись.

Ни `engines`, ни `.nvmrc` в проекте нет — других мест, где закреплён major,
не осталось (проверено grep'ом по Dockerfile/yml/md).

Совместимость: next 15.5.24 поддерживает node 20/22/24; sharp 0.35.4 — node
^18.17 || ^20.3 || >=22, prebuild linuxmusl-x64 есть.

Приёмка — этот самый CI: джобы фронтов теперь выполняются на node 24, так что
зелёный прогон PR и есть доказательство. Локально проверить нечем — на машине
node 26, это не тот major.
2026-08-29 14:02:55 +03:00

85 lines
4.5 KiB
Docker
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Trade-In MVP frontend — Next.js 15 + React 19 + TanStack Query.
# Без Sentry/Tailwind/Leaflet/echarts — лёгкая версия только для trade-in.
# ---- deps ----
FROM node:24-alpine AS deps
WORKDIR /app
# Лок ОБЯЗАТЕЛЕН (без `*`): `npm ci` без него падает, и это правильно —
# отсутствие лока раньше молча давало `npm install`, т.е. состав зависимостей
# определялся датой сборки (#2770).
COPY package.json package-lock.json ./
# --legacy-peer-deps: React 19 peer-dep mismatches (как в соседнем frontend/).
RUN --mount=type=cache,target=/root/.npm \
npm ci --legacy-peer-deps --no-audit --no-fund
# ---- builder ----
FROM node:24-alpine AS builder
WORKDIR /app
ENV NEXT_TELEMETRY_DISABLED=1
# basePath + API-prefix baked-in во время build (Next.js — build-time only).
# В CI workflow для prod:
# --build-arg NEXT_PUBLIC_BASE_PATH=/trade-in
# --build-arg NEXT_PUBLIC_API_BASE_URL=/trade-in
# В локальном dev: оба пусто = no-op (same-origin).
ARG NEXT_PUBLIC_BASE_PATH=""
ENV NEXT_PUBLIC_BASE_PATH=$NEXT_PUBLIC_BASE_PATH
ARG NEXT_PUBLIC_API_BASE_URL=""
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
ARG NEXT_PUBLIC_ENABLE_PREVIEW=""
ENV NEXT_PUBLIC_ENABLE_PREVIEW=$NEXT_PUBLIC_ENABLE_PREVIEW
# Версия продукта («Мера») + короткий git SHA + дата сборки — ДОЛЖНЫ быть
# build-time ARG (не runtime env): Next.js инлайнит NEXT_PUBLIC_* в статические
# бандлы на `npm run build`, а этот build context (./tradein-mvp/frontend) не
# видит tradein-mvp/VERSION (он на уровень выше, вне build context) — источник
# правды читает CI ДО вызова `docker build` (.forgejo/workflows/deploy-tradein.yml,
# job build-frontend) и передаёт сюда готовыми значениями. Пустые дефолты — для
# локальной сборки без CI; фолбэк на "VERSION-файл/dev/дата сборки" делает уже
# frontend-код, потребляющий эти env (Dockerfile сам файл не читает).
ARG NEXT_PUBLIC_APP_VERSION=""
ENV NEXT_PUBLIC_APP_VERSION=$NEXT_PUBLIC_APP_VERSION
ARG NEXT_PUBLIC_BUILD_SHA=""
ENV NEXT_PUBLIC_BUILD_SHA=$NEXT_PUBLIC_BUILD_SHA
ARG NEXT_PUBLIC_BUILD_DATE=""
ENV NEXT_PUBLIC_BUILD_DATE=$NEXT_PUBLIC_BUILD_DATE
# CHANGELOG.md — источник для /versions (src/lib/changelog.ts). Живёт на
# уровень выше этого build context (tradein-mvp/CHANGELOG.md), поэтому CI
# копирует его СЮДА (tradein-mvp/frontend/CHANGELOG.md) непосредственно
# перед `docker build` (см. .forgejo/workflows/deploy-tradein.yml, job
# build-frontend) — `COPY . .` ниже подхватывает её автоматически вместе с
# остальным контекстом. Локальная сборка без этого шага CI просто не находит
# файл — readChangelog() уже умеет деградировать (пустая история), сам
# Docker-билд при этом не падает (см. glob-COPY в runner stage ниже).
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# ---- runner ----
FROM node:24-alpine AS runner
WORKDIR /app
# HOSTNAME=0.0.0.0 — Next.js standalone server.js биндится по этому env.
# Без него Docker ставит HOSTNAME=<container-id> и сервер недоступен по
# имени сервиса из других контейнеров (Caddy → 502).
ENV NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 \
HOSTNAME=0.0.0.0 \
PORT=3000
COPY --from=builder --chown=node:node /app/public ./public
COPY --from=builder --chown=node:node /app/.next/standalone ./
COPY --from=builder --chown=node:node /app/.next/static ./.next/static
# /versions — Server Component, statically prerendered at `npm run build`
# (see src/app/versions/page.tsx) — CHANGELOG.md's content is already baked
# into .next/standalone above. This is a defensive fallback ONLY, in case that
# page ever stops being static: glob (trailing `*`) makes it a no-op when the
# builder stage doesn't have the file either (local build without the CI
# pre-copy step, see builder stage comment above) — never fails the build.
COPY --from=builder --chown=node:node /app/CHANGELOG.md* ./
USER node
EXPOSE 3000
CMD ["node", "server.js"]