gendesign/tradein-mvp/frontend/Dockerfile
bot-backend 443de71ded
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Successful in 44s
CI Trade-In / frontend-checks (pull_request) Successful in 1m1s
CI Trade-In / backend-tests (pull_request) Successful in 3m53s
build(tradein/frontend): состав зависимостей перестаёт зависеть от даты сборки (#2770)
`pnpm-lock.yaml` лежал в репозитории 121 КБ и не читался НИКЕМ: Dockerfile
копировал `package-lock.json*` (которого не было) и ставил `npm install`,
`ci-tradein.yml` — тоже `npm install`, слова `pnpm` в репозитории больше нет
нигде, кроме комментария в самом workflow. Последняя правка — #2312, и с тех
пор `package.json` уезжал мимо него; #2769 (devDeps под vitest) развёл их
окончательно.

То есть это был не лок, а снимок дерева, которое никто не собирает. Хуже, чем
просто мусор: `pnpm install` из него отработал бы и дал дерево, отличное от
уехавшего в прод-образ, — расхождение обнаружилось бы позже и не там.

Из двух вариантов issue взят второй, потому что задуманное ВЫРАЗИМО и уже
выражено рядом: у соседнего `frontend/` ровно эта схема — tracked
`package-lock.json` + `npm ci`. Первый вариант (просто удалить) закрепил бы
невоспроизводимую установку: до этого коммита версии в CI и в прод-образе
выбирались независимо, каждая по дате своей сборки, и гейт проверял не тот
код, который деплоится.

Что сделано:
  • `tradein-mvp/frontend/package-lock.json` — сгенерирован и TRACKED
    (483 пакета, lockfileVersion 3, 12 записей swc-linux → ставится на linux
    из лока, снятого на macOS, как у соседнего frontend/);
  • `.gitignore` — снята строка `frontend/package-lock.json`. В issue сказано
    «в .gitignore не попадал — просто не коммитился»; это НЕВЕРНО, он там был
    (tradein-mvp/.gitignore:18), поэтому лок и не мог появиться сам;
  • Dockerfile: `npm install` → `npm ci`, `package-lock.json*` → без `*`
    (отсутствие лока обязано ронять сборку, а не молча включать install);
  • ci-tradein.yml: `npm install` → `npm ci` + `cache: npm` в setup-node;
  • .claude/rules/frontend.md — правило «правишь package.json → регенерируй
    лок в том же PR» распространено на tradein-фронт.

Верификация локально:
  • `npm ci` в node:20-alpine внутри `docker build` — образ собран целиком
    (deps → next build → runner), контейнер поднят, `/` отвечает 307;
  • все четыре шага гейта на новом локе: type-check ✓, vitest 13 passed ✓,
    next lint ✓ (только преды, довоенные), mera-public isolation ✓.

Closes #2770
2026-08-07 13:34:46 +05:00

55 lines
2.1 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:20-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:20-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
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# ---- runner ----
FROM node:20-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
USER node
EXPOSE 3000
CMD ["node", "server.js"]