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