Docker: для разработки vs для продакшна

Development и production Dockerfile имеют разные приоритеты: dev-образ оптимизирован для скорости итерации, production-образ — для безопасности, размера и производительности.

Зачем нужно

Один и тот же Dockerfile не подходит для обеих задач: в разработке нужны devDependencies, hot reload и bind mount; в продакшне — минимальный образ без лишних инструментов, правильный пользователь (не root) и только production-зависимости. Разделение конфигураций предотвращает случайную публикацию debug-инструментов в прод.

Где используется

  • Dockerfile + Dockerfile.dev — отдельные файлы для каждой среды
  • docker-compose.yml + docker-compose.override.yml — base + dev-оверрайд
  • Multi-stage build — один Dockerfile с несколькими FROM для разных таргетов

Основной контент

Dockerfile для разработки

# Dockerfile.dev
FROM node:20-alpine
WORKDIR /app

# Устанавливаем всё, включая devDependencies
COPY package*.json() ./
RUN npm ci

# Код монтируется через bind mount — не копируем!
EXPOSE 3000

# nodemon для hot reload
CMD ["npx", "nodemon", "--watch", "src", "src/index.ts"]

Dockerfile для продакшна

# Dockerfile (production)
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json() ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS production
# Минимальные права — не root!
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app

COPY package*.json() ./
RUN npm ci --omit=dev && npm cache clean --force

COPY --from=builder /app/dist ./dist

USER appuser          # переключаемся на непривилегированного пользователя
EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget -qO- http://localhost:3000/health || exit 1

CMD ["node", "dist/index.js"]

docker-compose с оверрайдом

# docker-compose.yml (base, работает для всех сред)
services:
  api:
    image: myapp:${TAG:-latest}
    environment:
      NODE_ENV: production
    ports:
      - "3000:3000"
    restart: unless-stopped
# docker-compose.override.yml (применяется автоматически в разработке)
services:
  api:
    build:
      context: .
      dockerfile: Dockerfile.dev
    image: myapp:dev
    environment:
      NODE_ENV: development
    volumes:
      - .:/app
      - /app/node_modules
    command: npx nodemon src/index.ts
# Разработка
docker compose up

# Продакшн (явно без override)
docker compose -f docker-compose.yml up

Сравнение

Аспект Development Production
Зависимости Все (включая dev) Только production
Код Bind mount (hot reload) Скопирован внутрь образа
Размер образа ~500 MB+ ~100-200 MB (multi-stage)
Пользователь root (по умолчанию) непривилегированный
CMD nodemon / ts-node node (скомпилированный JS)

Частые ошибки

  • Деплой dev-образа в продакшн: он содержит devDependencies, исходники и debug-инструменты
  • Запуск production-контейнера от root — критический риск безопасности
  • Копирование .env файла внутрь продакшн-образа — секреты становятся частью образа

Связанные темы

Ресурсы