Код-ревью Middle Dockerfile и multi-stage обновлено

Ревью: Dockerfile для Node.js

Вопрос

Найди проблемы в Dockerfile Node.js-сервиса.

FROM node:22
COPY . /app
WORKDIR /app
ENV NPM_TOKEN=npm_9fQx1example
RUN npm install
RUN npm run build
EXPOSE 3000
CMD npm start

Коротко

Исправленная версия: Секрет передаётся docker build --secret id=npmrc,src=$HOME/.npmrc и не попадает в слои. Зависимости ставятся из lock-файла, в финале только продовые, код копируется после установки, процесс запускается напрямую от непривилегированного пользователя.

Что должен найти ревьюер

  1. Производительностьстрока 1
    Полный образ node:22 весит около гигабайта и тащит компиляторы в прод. Нужна multi-stage сборка с финальной стадией на node:22-slim или distroless.
  2. Производительностьстрока 2
    COPY . /app до установки зависимостей: любое изменение кода сбрасывает кеш npm install. Сначала копировать package*.json.
  3. Безопасностьстрока 4
    Токен реестра в ENV навсегда остаётся в образе и в docker history. Использовать RUN --mount=type=secret.
  4. Ошибкастрока 5
    npm install может обновить lock-файл и ставит dev-зависимости в прод. Для сборки npm ci, в финальном образе npm ci --omit=dev.
  5. Ошибкастрока 8
    Shell-форма и npm start: PID 1 будет shell, а npm ещё одной прослойкой; SIGTERM не дойдёт до node. Нужно CMD ["node", "dist/server.js"].
  6. Безопасность
    Нет USER: процесс работает от root. В официальном образе есть пользователь node.

Разбор

Исправленная версия:

# syntax=docker/dockerfile:1
FROM node:22 AS build
WORKDIR /app
COPY package*.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci
COPY . .
RUN npm run build

FROM node:22-slim
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci --omit=dev
COPY --from=build /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]

Секрет передаётся docker build --secret id=npmrc,src=$HOME/.npmrc и не попадает в слои. Зависимости ставятся из lock-файла, в финале только продовые, код копируется после установки, процесс запускается напрямую от непривилегированного пользователя. Ещё нужен .dockerignore с node_modules и .git.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.