Приходилось ли писать Docker файлы и работать с контейнерами
Что проверяют
Понимаете ли вы, что фронтенд в контейнере это две разные вещи: окружение сборки и то, что отдаёт файлы пользователю. По ответу видно, участвовали ли вы в выкате или работа заканчивалась на пуше в ветку.
Как отвечать
Опишите двухступенчатый образ. Первый этап на образе с Node ставит зависимости через npm ci и делает сборку. Второй берёт лёгкий веб-сервер, обычно nginx, и получает из первого только каталог с готовой статикой. Инструменты сборки в финальный образ не едут.
Отдельно назовите то, что относится именно к фронтенду:
- фолбэк для клиентского роутинга:
try_files $uri /index.html, иначе обновление страницы на вложенном адресе даёт ответ 404 от сервера; - заголовки кэширования: файлы с хешем в имени кэшируются надолго,
index.htmlне кэшируется никогда; - сжатие ответов и корректные типы содержимого;
.dockerignore, чтобы локальныеnode_modulesне попадали в контекст сборки.
Главный нюанс это переменные окружения. Значения вроде адреса API вклеиваются в бандл на этапе сборки, поэтому один образ на все стенды подходит, только если адрес читается в рантайме: из отдельного файла конфигурации, который подкладывают при старте контейнера, или с того же домена по относительному пути. Иначе на каждое окружение собирается свой образ, и это стоит проговорить осознанно.
Для Next.js добавьте, что образ получается другим: там живёт серверный процесс, и собирают его в отдельном режиме с минимальным набором файлов.
Где спотыкаются
Кладут в образ дев-сервер и запускают его в проде. Он держит слежение за файлами, отдаёт несжатые файлы и карты кода, а перезапуск контейнера превращается в пересборку.
Ждут, что адрес API можно передать флагом при запуске контейнера. В собранном бандле на его месте уже стоит подставленная строка, и никакой запуск её не изменит.
Путают EXPOSE с публикацией порта. Инструкция в Dockerfile ничего не открывает наружу, а внутри контейнера сервер слушает свой порт, и несовпадение с портом сервиса выглядит как «образ не работает».