JS Tower
Node.jsМодуль 7: Тестирование и деплой

Docker

Dockerfile, docker-compose, контейнеризация

Цель урока

В этом уроке ты научишься:

  • Создавать Dockerfile для Node.js
  • Использовать docker-compose
  • Оптимизировать образы

Dockerfile

Базовый Dockerfile

# Dockerfile
FROM node:20-alpine

WORKDIR /app

COPY package*.json ./

RUN npm ci --only=production

COPY . .

EXPOSE 3000

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

Оптимизированный Dockerfile

# Build stage
FROM node:20-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

# Production stage
FROM node:20-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force

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

USER node

EXPOSE 3000

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

.dockerignore

node_modules
npm-debug.log
.git
.gitignore
.env
.env.*
Dockerfile
docker-compose.yml
coverage
.nyc_output
logs
*.log

docker-compose

Базовый

# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=mongodb://mongo:27017/myapp
    depends_on:
      - mongo
    restart: unless-stopped

  mongo:
    image: mongo:7
    volumes:
      - mongo_data:/data/db
    restart: unless-stopped

volumes:
  mongo_data:

С Redis и PostgreSQL

version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:pass@postgres:5432/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      - postgres
      - redis
    restart: unless-stopped

  postgres:
    image: postgres:16-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    restart: unless-stopped

volumes:
  postgres_data:

Команды Docker

# Сборка образа
docker build -t my-app .

# Запуск контейнера
docker run -p 3000:3000 my-app

# С переменными окружения
docker run -p 3000:3000 -e NODE_ENV=production my-app

# docker-compose
docker-compose up -d          # Запуск
docker-compose down           # Остановка
docker-compose logs -f app    # Логи
docker-compose exec app sh    # Войти в контейнер
docker-compose build          # Пересборка

Development с Docker

# docker-compose.dev.yml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
    command: npm run dev
# Dockerfile.dev
FROM node:20-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

CMD ["npm", "run", "dev"]
docker-compose -f docker-compose.dev.yml up

Health Check

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
// Endpoint для health check
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date() });
});

Практика

Задание: Docker для API

Задача: Создай Docker конфигурацию для API с MongoDB.

Решение:

# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "src/index.js"]
# docker-compose.yml
version: '3.8'
services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=mongodb://mongo:27017/api
    depends_on:
      - mongo
  mongo:
    image: mongo:7
    volumes:
      - mongo_data:/data/db
volumes:
  mongo_data:

Проверь себя

  1. Зачем нужен multi-stage build?
  2. Что делает .dockerignore?
  3. Как передать переменные окружения?