Гид по технологиям

Docker для Node.js с PostgreSQL

6 min read DevOps Обновлено 11 Apr 2026
Docker для Node.js с PostgreSQL
Docker для Node.js с PostgreSQL

Логотип Docker на тёмном фоне

Важно: все команды выполняйте из корня проекта, если иначе не указано.

Зачем использовать Docker

Docker позволяет упаковать приложение и все зависимости в образ, который будет одинаково работать на локальной машине, в CI или в облаке. Контейнеры минимизируют проблему “у меня работает на моей машине” и стандартизируют окружения.

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

Что включает пример

В этом руководстве вы найдёте:

  • Пример простого Node.js REST API с тремя маршрутами.
  • Конфигурацию подключения к PostgreSQL через knex/pg.
  • Скрипты миграции и наполнения (migrate.js, seed.js).
  • Dockerfile для приложения и docker-compose.yml для запуска приложения + базы в одной сети.
  • Команды для сборки, запуска, тестирования и публикации образа.

Требования

  • Установленный Docker и Docker Compose (или Docker Desktop).
  • Node.js и npm для локальной разработки (для тестов вне контейнера).
  • Аккаунт на Docker Hub для публикации образов (опционально).

Примечание: для Windows рекомендуется включить WSL2 и использовать Docker Desktop для стабильной работы.

Грузовые корабли в порту, иллюстрация концепции развёртывания

Создаём Node.js REST API

  1. Инициализируйте проект npm и установите зависимости:
npm install morgan pg knex
  1. Пояснение пакетов:
  • pg — драйвер для PostgreSQL.
  • knex — query builder для удобной работы с SQL.
  • morgan — логирование HTTP-запросов для отладки.
  1. Создайте файл index.js и вставьте следующий код:
const express = require("express")  
const morgan = require("morgan")  
const app = express()  
const db = require('./db')  
const PORT = process.env.PORT || 5000  
  
app.use(morgan('dev'))  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))  
  
app.get('/', (req, res) => res.send('Hello World!' ))  
  
app.get('/users', async (req, res) => {  
  const users = await db.select().from('users')  
  res.json(users)  
})  
  
app.post('/users', async (req, res) => {  
  const user = await db('users').insert({ name: req.body.name }).returning('*')  
  res.json(user)  
})  
  
app.listen(PORT, () => console.log(`Server up at PORT:${PORT}`))

Важно: код выше рассчитан на работу с таблицей users в схеме public PostgreSQL.

Настройка подключения к базе

Создайте файл db.js в корне проекта со следующим содержимым:

const knex = require('knex')  
module.exports = knex({  
  client: 'postgres',  
  connection: {  
    host: 'db',  
    user: 'testUser',  
    password: 'mypassword123',  
    database: 'testUser',  
      
  },  
})

Здесь host: ‘db’ соответствует имени сервиса базы в docker-compose.yml.

Совет по безопасности: не храните пароли в коде в продакшне — используйте переменные окружения или Docker secrets.

Скрипты миграции и наполнения

Создайте папку scripts и два файла: migrate.js и seed.js.

migrate.js:

const db = require('../db');  
(async () => {  
  try {  
    await db.schema.dropTableIfExists('users')  
    await db.schema.withSchema('public').createTable('users', (table) => {  
      table.increments()  
      table.string('name')  
    })  
    console.log('Created users table!')  
    process.exit(0)  
  } catch (err) {  
    console.log(err)  
    process.exit(1)  
  }  
})()

seed.js:

const db = require('../db');  
(async () => {  
  try {  
    await db('users').insert({ name: 'Test User1' })  
    await db('users').insert({ name: 'Test User2' })  
    console.log('Added dummy users!')  
    process.exit(0)  
  } catch (err) {  
    console.log(err)  
    process.exit(1)  
  }  
})()

Добавьте в package.json команды:

  "scripts": {  
    "start": "node index.js",  
    "migrate": "node scripts/migrate.js",  
    "seed": "node scripts/seed.js"  
  
  },

Пояснение: npm run migrate и npm run seed выполнятся внутри контейнера или локально для инициализации данных.

Dockerfile

Создайте Dockerfile в корне проекта с таким содержимым:

FROM node:16.3.0-alpine3.13  
WORKDIR /app  
COPY package*.json ./  
RUN npm install  
COPY . .  
EXPOSE 8000  
CMD [ "node", "index.js" ]

Разбор инструкций:

  • FROM — базовый образ Node.js (alpine — лёгкий).
  • WORKDIR — рабочая директория внутри контейнера.
  • COPY package*.json ./ — копирует package.json + package-lock.json (если есть) для кеширования npm install.
  • RUN npm install — устанавливает зависимости при сборке образа.
  • COPY . . — копирует исходники.
  • EXPOSE — декларативно указывает порт (в этом Dockerfile указан 8000, а в приложении слушается 5000; проверьте согласованность или используйте env PORT).
  • CMD — команда запуска приложения.

Важно: приведённый Dockerfile объявляет EXPOSE 8000, тогда как приложение по умолчанию использует 5000. Согласуйте PORT через переменную окружения, чтобы избежать несоответствий.

docker-compose.yml

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

version: '3.9'  
  
services:  
  server:  
    build: .  
    ports:  
      - '5000:5000'  
    depends_on:  
      - db  
  db:  
    image: 'postgres'  
    ports:  
      - '4321:5432'  
    environment:  
      POSTGRES_PASSWORD: 'mypassword123'  
      POSTGRES_USER: 'testUser'  
    volumes:  
      - data:/var/lib/postgresql/data  
  
volumes:  
  data:

Разъяснение:

  • server собирается из локального Dockerfile.
  • db использует официальный образ postgres.
  • ports у db пробрасывает порт 5432 контейнера на 4321 хоста (полезно для локального доступа к БД).
  • volumes сохраняет данные PostgreSQL между перезапусками.

Совет: для разработки указывайте переменные окружения через .env файл и docker-compose поддерживает ссылку на него.

Сборка и запуск

Сборка и запуск в фоне:

docker-compose up -d

Вы увидите вывод создания контейнеров и их запуск.

Два контейнера Docker запущены на движке Docker

Тестирование API

Выполните миграцию внутри запущенного контейнера сервера (имя контейнера может отличаться):

docker exec docker_node-server-1 npm run migrate

Вы должны увидеть логи создания таблицы.

Лог сервера после выполнения скрипта миграции, таблица создана

Альтернативный способ: напрямую запустить migrate как одноразовый сервис в docker-compose:

  migrate:
    build: .
    command: npm run migrate
    depends_on:
      - db

Это удобно для CI.

Публикация образа на Docker Hub

  1. Зарегистрируйтесь на Docker Hub и создайте репозиторий.
  2. Авторизуйтесь в терминале:
docker login
  1. Пометьте образ (tag) в формате /:
 docker tag  /
  1. Запушьте образ:
 docker push /

Примечание: используйте CI/CD для автоматической сборки и публикации образов из ветки main.

Практические рекомендации и варианты

Когда Docker не лучший выбор

  • Очень мелкие скрипты, запускающиеся однократно на локальной машине — добавление контейнера может быть избыточно.
  • Жёсткие требования к аппаратным ресурсам или драйверам хоста (например, GPU на специфическом ПО) — лучше использовать нативные установки или специальные контейнерные технологии.

Альтернативы и экосистема

  • Podman — бесcистемный аналог Docker, может работать rootless.
  • Kubernetes — если нужно оркестрирование нескольких сервисов в продакшне.
  • Docker Desktop / Rancher Desktop — удобные GUI-решения для локальной разработки.

Ментальные модели

  • Образ = снимок файловой системы + метаданные.
  • Контейнер = запущенный экземпляр образа.
  • Compose = набор сервисов, настроенных как единый стек.

Порядок действий для проверки (SOP)

  1. git pull && npm install (локально).
  2. docker-compose build.
  3. docker-compose up -d.
  4. docker exec npm run migrate.
  5. docker exec npm run seed.
  6. Тестировать endpoints через curl/Postman.

Проверочный список ролей

Разработчик:

  • Код валидируется eslint/jest.
  • Добавлены миграции и seed.

DevOps/Инженер релиза:

  • Есть Dockerfile и docker-compose.yml.
  • CI собирает образ и пушит на Docker Registry.

QA:

  • Тестовые сценарии на доступность endpoint, корректность статусов и данных.

Тестовые сценарии и команды

Проверить GET /users:

curl -s http://localhost:5000/users | jq

Добавить пользователя:

curl -X POST http://localhost:5000/users -H 'Content-Type: application/json' -d '{"name":"Новый пользователь"}'

Критерии приёмки

  • Сервер отвечает на / со статусом 200 и текстом Hello World!.
  • GET /users возвращает массив пользователей после миграции и seed.
  • POST /users добавляет запись и возвращает вставленного пользователя.

Безопасность и конфиденциальность

  • Не храните учётные данные в публичных репозиториях.
  • Для секретов в продакшне используйте Docker secrets, HashiCorp Vault или переменные окружения в CI.
  • Для персональных данных учитывайте требования локального законодательства и GDPR: храните минимально необходимые данные, документируйте основания обработки и срок хранения.

Отладка и типичные проблемы

  • Проблема: контейнер сервера не может подключиться к БД.

    • Проверьте имя хоста в db.js — должно совпадать с именем сервиса в docker-compose (db).
    • Убедитесь, что db контейнер поднят: docker-compose ps.
  • Проблема: порт не доступен.

    • Проверяйте соответствие EXPOSE в Dockerfile и проброса портов в docker-compose.
  • Проблема: npm install долго выполняется при сборке.

    • Используйте COPY package*.json + RUN npm install до копирования всего кода, чтобы кешировать слои.

Локальные нюансы и рекомендации для России

  • Для доступа к Docker Hub может понадобиться настройка прокси или подключение через альтернативные зеркала в корпоративных сетях.
  • Для приватных реестров используйте GitLab Container Registry, AWS ECR или GitHub Packages, если политика компании ограничивает публичный Docker Hub.

Заключение

Docker делает развёртывание и воспроизводимость окружений простыми и предсказуемыми. В этом руководстве показан базовый путь упаковки Node.js приложения с PostgreSQL и лучшие практики для разработки, тестирования и деплоя.

Ключевые шаги:

  • Подготовьте приложение и миграции.
  • Напишите Dockerfile и docker-compose.yml.
  • Соберите, запустите, мигрируйте и тестируйте.
  • Публикуйте образы в реестр в рамках CI/CD.

Важно: проверяйте настройки портов и секретов перед деплоем в продакшен.

Подготовьте следующий шаг: добавить Dockerfile для продакшен-сборки с multi-stage, добавить healthchecks и readiness probes, а при масштабировании — перенести на Kubernetes.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро