Docker и JavaScript: контейнеризация Node.js приложений с нуля

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Docker и JavaScript: Полное руководство по контейнеризации Node.js приложений

Современная веб-разработка немыслима без контейнеризации. Docker стал стандартом де-факто для упаковки, доставки и запуска приложений в изолированных средах. В этой статье мы подробно разберем, как использовать Docker для контейнеризации JavaScript-приложений на Node.js. Вы узнаете, как создать оптимизированный Dockerfile, управлять образами и контейнерами, а также познакомитесь с лучшими практиками.

Что такое Docker и зачем он нужен JavaScript-разработчику?

Docker — это платформа для разработки, доставки и запуска приложений в контейнерах. Контейнер — это легковесная, автономная, исполняемая среда, которая содержит все необходимое для работы приложения: код, runtime, системные инструменты, библиотеки и настройки.

Для JavaScript-разработчика, работающего с Node.js, Docker решает несколько ключевых проблем:

  • Воспроизводимость окружения: "На моей машине работает" — больше не проблема. Docker гарантирует, что приложение будет работать одинаково на компьютере разработчика, сервере CI/CD и в production.
  • Изоляция зависимостей: Каждое приложение получает собственный набор зависимостей, не конфликтуя с другими проектами.
  • Упрощение развертывания: Docker-образ можно легко запустить на любой платформе, поддерживающей Docker (Linux, Windows, macOS, облачные серверы).
  • Масштабирование: Контейнеры легко масштабировать горизонтально с помощью оркестраторов вроде Docker Compose или Kubernetes.

Создание Dockerfile для Node.js приложения

Dockerfile — это текстовый файл с инструкциями для сборки Docker-образа. Рассмотрим пошаговое создание Dockerfile для типичного Express.js приложения.

Предположим, у нас есть простое Node.js приложение со следующей структурой:

my-node-app/
├── package.json
├── package-lock.json
├── src/
│   └── index.js
└── Dockerfile

Содержимое src/index.js:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.get('/', (req, res) => {
    res.send('Hello from Dockerized Node.js!');
});

app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
});

Теперь создадим Dockerfile:

# Используем официальный образ Node.js версии 18 (LTS)
FROM node:18-alpine

# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /usr/src/app

# Копируем файлы package.json и package-lock.json
COPY package*.json ./

# Устанавливаем зависимости приложения
RUN npm ci --only=production

# Копируем исходный код приложения
COPY . .

# Указываем порт, который будет слушать приложение
EXPOSE 3000

# Команда для запуска приложения
CMD ["node", "src/index.js"]

Разберем ключевые моменты:

  • FROM node:18-alpine — используем минимальный образ на основе Alpine Linux. Это значительно уменьшает размер итогового образа.
  • WORKDIR — задает рабочую директорию. Все последующие команды будут выполняться относительно нее.
  • COPY package*.json ./ — копируем только файлы с зависимостями до копирования исходного кода. Это позволяет кэшировать слой с установкой зависимостей, если package.json не изменился.
  • RUN npm ci --only=production — устанавливает зависимости из lock-файла. Флаг --only=production исключает dev-зависимости (тесты, линтеры и т.д.), что уменьшает размер образа.
  • EXPOSE 3000 — документально указывает, что приложение слушает порт 3000. Это не открывает порт автоматически, но служит подсказкой для Docker.

Сборка и запуск контейнера

После создания Dockerfile выполните сборку образа:

docker build -t my-node-app:latest .

Флаг -t задает имя и тег образа. Точка в конце указывает на текущую директорию как контекст сборки.

Запустите контейнер из собранного образа:

docker run -d -p 8080:3000 --name my-node-container my-node-app:latest

Параметры:

  • -d — запуск в фоновом режиме (detached).
  • -p 8080:3000 — пробрасывает порт 8080 хоста на порт 3000 контейнера. Теперь приложение доступно по адресу http://localhost:8080.
  • --name — задает имя контейнера для удобного управления.

Проверьте, что приложение работает:

curl http://localhost:8080
# Вывод: Hello from Dockerized Node.js!

Остановить и удалить контейнер можно командами:

docker stop my-node-container
docker rm my-node-container

Использование Docker Compose для многоконтейнерных приложений

В реальных проектах Node.js-приложение часто требует базу данных (например, PostgreSQL или MongoDB), кэш (Redis) и другие сервисы. Docker Compose позволяет описать и запустить многоконтейнерное приложение одной командой.

Создайте файл docker-compose.yml в корне проекта:

version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_PORT=5432
    depends_on:
      - db
    volumes:
      - .:/usr/src/app
      - /usr/src/app/node_modules

  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=app_user
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  postgres_data:

Объяснение:

  • services — определяет два сервиса: app (наше Node.js приложение) и db (PostgreSQL).
  • <

Блоги

Рекомендаций по книгам