Приходилось ли писать Docker файлы и работать с контейнерами
Что проверяют
Собирали ли вы образ сами или получали готовый от платформы. Для Node.js это не формальность: половина проблем с контейнером относится не к Docker, а к тому, как процесс Node ведёт себя в роли первого процесса и что попало в образ вместе с кодом.
Как отвечать
Опишите свой типовой Dockerfile и объясните каждое решение:
- многоступенчатая сборка: на первом этапе ставятся все зависимости и собирается проект, в финальный образ едут только продакшен-зависимости и результат сборки;
COPY package*.json ./и установка до копирования исходников, иначе кэш слоёв ломается на каждой правке кода;npm ciвместоnpm install: ставится ровно то, что в lock-файле, и сборка падает при расхождении;.dockerignoreсnode_modules,.gitи локальными артефактами;USER node, чтобы процесс не работал от суперпользователя.
Про сигналы скажите обязательно. При выкате контейнер получает SIGTERM, и если запуск описан через оболочку или обёрнут в npm-скрипт, сигнал до приложения не доходит: через отведённое время процесс убивают жёстко, а незавершённые запросы обрываются. Отсюда CMD ["node", "server.js"], подписка на SIGTERM, server.close() и закрытие пула соединений.
Закончите эксплуатацией: теги образов по версии, а не плавающий latest, секреты передаются при запуске, а не строкой в Dockerfile, где они навсегда остаются в слое.
Где спотыкаются
Запускают приложение через npm start. Менеджер пакетов становится первым процессом, сигнал не транслируется, корректного завершения нет. Со стороны это выглядит как случайные ошибки у пользователей ровно во время деплоя.
Копируют всё подряд без .dockerignore. В образ уезжают node_modules с машины разработчика, и нативные модули, собранные под другую систему, падают уже в контейнере.
Гонятся за минимальным образом и берут alpine, не проверив нативные зависимости. Там другая реализация стандартной библиотеки C, и пакеты с бинарными модулями приходится пересобирать, а иногда они просто не заводятся.