Первый коммит существующего состояния. Ядро кладётся под git ради того, чтобы половины разъезжались в продуктовые репозитории через git subtree, а не копированием: subtree делает настоящий merge, хранит историю и умеет отдавать правки обратно. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LeBkZLiQrvdECf5nfgiMz
57 lines
3.1 KiB
Docker
57 lines
3.1 KiB
Docker
# syntax=docker/dockerfile:1
|
||
|
||
# Панель — один процесс и один образ: express отдаёт и API, и собранный фронт
|
||
# (core/server/spa.ts), отдельный nginx ей не нужен.
|
||
#
|
||
# Контекст сборки — каталог самой панели, и ничего выше него не требуется:
|
||
# вендоренная копия ядра закоммичена вместе с исходниками, поэтому образ
|
||
# собирается из чистого checkout'а, без ma7engine рядом. Обновляется копия
|
||
# отдельно и осознанно — `npm run update` во фронте, диффом в ревью.
|
||
#
|
||
# docker build -t admin-hub .
|
||
# docker run -p 8080:8080 -e ADMIN_PASS=… -e ADMIN_JWT_SECRET=… admin-hub
|
||
|
||
# ─── фронт: собирается и остаётся только как dist ───────────────────────────
|
||
FROM node:24-alpine AS frontend
|
||
WORKDIR /app/frontend
|
||
|
||
COPY frontend/package.json frontend/package-lock.json ./
|
||
RUN npm ci
|
||
|
||
COPY frontend/ ./
|
||
# prebuild зовёт update.sh. Ядра рядом в образе нет, и скрипт штатно берёт уже
|
||
# синхронизированную копию из src/core — это его нормальная ветка, не ошибка.
|
||
RUN npm run build
|
||
|
||
# ─── рантайм: бэкенд плюс собранный фронт ───────────────────────────────────
|
||
FROM node:24-alpine AS runtime
|
||
WORKDIR /app/backend
|
||
|
||
COPY backend/package.json backend/package-lock.json ./
|
||
# tsx лежит в dependencies намеренно: сервер и в деве, и в образе стартует одной
|
||
# и той же командой. Компиляция в JS дала бы образ меньше, но развела бы дев и
|
||
# прод, а в этой панели пути и команды всюду одинаковы — на том же основании
|
||
# ядро ездит копией, а не алиасом.
|
||
RUN npm ci --omit=dev
|
||
|
||
COPY backend/ ./
|
||
# staticDir по умолчанию — ../frontend/dist от каталога сервера.
|
||
COPY --from=frontend /app/frontend/dist /app/frontend/dist
|
||
|
||
ENV NODE_ENV=production
|
||
ENV PORT=8080
|
||
EXPOSE 8080
|
||
|
||
# NODE_ENV=production включает разбор X-Forwarded-For в рейт-лимите: за прокси
|
||
# без него все клиенты схлопываются в один ключ и блокируют вход всем сразу.
|
||
#
|
||
# ADMIN_PASS (или ADMIN_PASS_HASH) и ADMIN_JWT_SECRET значений по умолчанию не
|
||
# имеют — без них процесс не поднимется. Это не недосмотр: тихо работающая
|
||
# панель с паролем по умолчанию хуже не стартовавшей.
|
||
USER node
|
||
|
||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||
CMD wget -qO- "http://127.0.0.1:${PORT}/" >/dev/null 2>&1 || exit 1
|
||
|
||
CMD ["npm", "start"]
|