«У мене працює» — фраза, яку Docker має знищити. Для фронтендера це не про Kubernetes, а про дві речі: відтворювану збірку та середовище, яке нова людина в команді запускає однією командою.
Багатоетапний Dockerfile
Перший етап збирає застосунок на образі з Node. Другий бере лише готову теку dist і віддає її через nginx. Фінальний образ не містить ні Node, ні node_modules — важить десятки мегабайтів замість сотень.
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
Порядок рядків важливий. Спершу копіюємо лише package*.json і ставимо залежності — Docker закешує цей шар, і зміна самого коду не змусить усе перевстановлювати.
.dockerignore
Без нього в образ потрапить локальний node_modules, збірка триватиме довше й може відрізнятися від тієї, що на CI.
node_modules
dist
.git
.env*
Compose для локальної роботи
Для розробки ми не збираємо образ на кожну зміну. Монтуємо код як том і запускаємо dev-сервер Vite у контейнері. Другий том, /app/node_modules, не дає залежностям із контейнера змішуватися з тими, що на вашому диску.
services:
web:
image: node:22-alpine
working_dir: /app
command: sh -c "npm ci && npm run dev -- --host"
ports:
- "5173:5173"
volumes:
- .:/app
- /app/node_modules
Три команди на щодень
| Команда | Що робить |
|---|---|
docker compose up | запускає середовище розробки |
docker build -t app . | збирає продакшн-образ |
docker run -p 8080:80 app | віддає збірку на localhost:8080 |
Обережно з SPA Стандартний nginx поверне 404 для маршрутів роутера після оновлення сторінки. Додайте власний конфіг із try_files $uri /index.html;.
От і все. З цими двома файлами збірка на CI, у вас і в колеги з новим ноутбуком дає однаковий результат.
