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

Docker и Nest.js: настройка приложения и базы в Docker Compose

7 min read DevOps Обновлено 28 Mar 2026
Docker + Nest.js: Docker Compose для разработки
Docker + Nest.js: Docker Compose для разработки

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

“Но у меня на компьютере всё работает…” — шутка отражает реальную проблему: среда разработки и среда развертывания часто различаются. Основная боль — согласовать версии ПО и зависимости. Решение — контейнеризация: упаковка приложения вместе с зависимостями в образ, который гарантированно запускается одинаково в любой среде.

Понимание Docker и Docker Compose

Docker — это открытая платформа для контейнеризации приложений. Контейнеры изолируют приложение и его зависимости, но не эмулируют полноценную виртуальную машину: они делят ядро ОС и обеспечивают лёгкую портируемость.

Определение в одну строку: контейнер — лёгкая изолированная среда для запуска приложения и зависимостей.

Docker Compose — инструмент для описания и управления многоконтейнерными приложениями через единый YAML-файл. Compose полезен, когда приложение состоит из нескольких сервисов (веб-сервер, БД, кеш и т.п.).

Грузовое судно с сотнями разноцветных контейнеров

Важно понимать различие:

  • Docker управляет отдельными образами и контейнерами.
  • Docker Compose описывает, как эти контейнеры связываются и запускаются как единое приложение.

Прежде чем начать: установите Docker Desktop и убедитесь, что ваша система соответствует требованиям платформы (документация Docker содержит актуальные шаги установки).

Код приложения можно версионировать и хранить в репозитории (например, GitHub) — это удобно при CI/CD.

Создание проекта Nest.js

В примере мы развернём два контейнера: один с приложением Nest.js, другой — с PostgreSQL.

Установите CLI Nest.js:

npm i -g @nestjs/cli

Создайте новый проект:

nest new docker-nest-app

Выберите предпочитаемый менеджер пакетов (npm или yarn). Пример использует npm.

Перейдите в каталог проекта и запустите dev-сервер для быстрой проверки:

cd docker-nest-app
npm run start

Модуль базы данных

Установите необходимые зависимости:

npm install pg typeorm @nestjs/typeorm @nestjs/config

Создайте файл .env в корне проекта и добавьте конфигурацию подключения к базе:

DATABASE_HOST="db"
DATABASE_PORT=5432
DATABASE_USER="testUser"
DATABASE_PASSWORD="mypassword123"

Примечание: для локальной разработки удобно использовать простые пароли, но в продакшене храните секреты в менеджерах секретов (Vault/Secrets Manager) или в Docker секретах.

Создайте модуль базы данных:

nest g module database

Откройте файл database/database.module.ts и вставьте конфигурацию TypeORM (как в исходном коде). Этот модуль подключит Nest приложение к PostgreSQL при запуске контейнера.

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot(),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        type: 'postgres',
        host: configService.get('DATABASE_HOST'),
        port: configService.get('DATABASE_PORT'),
        username: configService.get('DATABASE_USER'),
        password: configService.get('DATABASE_PASSWORD'),
        synchronize: true,
      }),
      inject: [ConfigService],
    }),
  ],
})

export class DatabaseModule {}

Короткое пояснение: опция synchronize: true удобна в разработке — TypeORM автоматически синхронизирует схему. В продакшене используйте миграции.

Обновление AppModule

Добавьте DatabaseModule и ConfigModule в главный модуль приложения:

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './database/database.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      envFilePath: '.env',
    }),
    DatabaseModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})

export class AppModule {}

Теперь приложение готово к контейнеризации: оно читает конфигурацию из .env (в контейнере переменные будут передаваться через Compose).

Создание Dockerfile

Dockerfile описывает шаги сборки образа приложения. В корне проекта создайте файл с именем Dockerfile и добавьте:

FROM node:16.3.0-alpine3.13
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD [ "npm", "run", "start:dev" ]

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

  1. FROM — базовый образ Node.js на Alpine Linux (лёгкий). При необходимости можно выбрать более новую версию node:18 или образ с распространёнными зависимостями.
  2. WORKDIR — рабочая директория внутри контейнера.
  3. COPY package*.json ./ — копирует package.json и package-lock.json для установки зависимостей до копирования остального кода (ускоряет кеширование слоёв).
  4. RUN npm install — устанавливает зависимости.
  5. COPY . . — копирует исходники.
  6. RUN npm run build — собирает TypeScript в папку dist.
  7. CMD — команда по умолчанию при запуске контейнера.

Советы и альтернативы:

  • Для production используйте multi-stage build: сначала собрать артефакты в builder-стадии, затем скопировать только нужные файлы в минимальный runtime-образ (node:16-alpine или даже scratch). Это уменьшит размер образа и поверхность атаки.

Пример упрощённого multi-stage Dockerfile:

# Build stage
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Production stage
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm ci --only=production
CMD [ "node", "dist/main.js" ]
  • Добавьте файл .dockerignore (пример ниже), чтобы не копировать лишние файлы в образ.

Пример .dockerignore:

node_modules
dist
.env
.git
npm-debug.log

Без .dockerignore вы рискуете увеличением размера образа и утечками конфиденциальных файлов.

Создание docker-compose.yml

В корне создайте docker-compose.yml с таким содержимым:

version: '3.9'

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

volumes:
  data:

Пояснения:

  • services.server.build: . — сборка образа приложения из локального Dockerfile.
  • depends_on гарантирует порядок запуска, но не ждёт готовности сервиса — можно добавить healthcheck для проверки состояния БД.
  • volumes.data сохраняет данные базы между перезапусками контейнеров.

Рекомендации:

  • Для надёжного запуска добавьте healthcheck к сервису db и используйте условие ожидания в сервере или внешнем скрипте ожидания (wait-for-it, dockerize).
  • На macOS/Windows Docker Desktop может иметь особенности работы с файловой системой — это влияет на производительность и категории прав доступа для томов.

Запуск контейнеров

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

docker compose up

Или запустить в фоне:

docker compose up -d

Просмотр логов:

docker compose logs -f

Основные проблемы при запуске и как их решать:

  • “Connection refused” от приложения к БД: проверьте переменные окружения, name сервиса в docker-compose (DATABASE_HOST должно быть “db”), и убедитесь, что БД успела подняться. Используйте healthcheck и ожидание.
  • Порт уже занят: убедитесь, что локальный порт 3000 или 5432 свободен, или измените сопоставление портов.
  • Разрешения тома PostgreSQL: иногда файлы в томе создаются с UID, отличным от UID внутри контейнера; решается выбором подходящего пользователя или использованием volume драйверов.

Вывод терминала с логами двух запущенных контейнеров Docker.

После успешного старта расширяйте приложение: добавьте CRUD API, миграции и тесты.

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

Публикация образа в Docker Hub похожа на пуш в Git. Короткая инструкция:

  1. Зарегистрируйтесь и войдите в Docker Hub.
  2. Создайте репозиторий (Public или Private).

Форма создания репозитория Docker Hub

  1. В терминале выполните логин:
docker login
  1. Пометьте (tag) локальный образ в формате /::
docker tag  /:latest
  1. Запушьте образ:
docker push /:latest

Замечания:

  • Убедитесь, что вы корректно указали тег — без него push не попадёт в требуемый репозиторий.
  • Для автоматической публикации в CI используйте docker login с токеном и секреты в CI-системе.

Когда контейнеризация не помогает (ограничения и контрпримеры)

  • Приложения с требованием к GPU и низкоуровнего доступа к оборудованию сложнее контейнеризовать; чаще используют специализированные образы и runtime (NVIDIA Container Toolkit).
  • Для GUI-приложений контейнеры не решают проблему локального рендеринга без дополнительной настройки X11/Wayland или VNC.
  • В высоконагруженных продакшен-сценариях иногда выгоднее использовать управляемые сервисы БД (RDS, Cloud SQL), а не контейнеры с базой данных.

Безопасность и соответствие требованиям конфиденциальности

  • Не храните секреты в Dockerfile или в образе. Используйте переменные окружения в Compose, Docker secrets или менеджеры секретов.
  • Не запускайте процессы в контейнере с root, если это не требуется. Укажите безопасного пользователя в Dockerfile (USER).
  • Минимизируйте размер образа и устанавливайте только необходимые пакеты.
  • Не храните персональные данные в образах и логах. Для соответствия GDPR удаляйте/анонимизируйте данные и используйте политики хранения.

Проверки, чек-листы и роли

Чек-лист для разработчика:

  • Приложение запускается локально без Docker.
  • Создан .env и пример .env.example без секретов.
  • TypeORM настроен на использование переменных окружения.
  • Есть .dockerignore для исключения лишних файлов.

Чек-лист для DevOps:

  • Dockerfile оптимизирован (многоступенчатая сборка для продакшена).
  • Есть healthcheck для БД и приложения.
  • Том для данных БД настроен и бэкапится.
  • Тесты CI собирают и пушат образ в реестр.

Чек-лист для QA:

  • Приложение проходит интеграционные тесты с контейнеризированной БД.
  • Мобильные/регрессионные тесты автоматизированы и запускаются в контейнерной среде, если возможно.

Мини-методология: как контейнеризовать приложение за 5 шагов

  1. Подготовьте конфигурацию приложения к чтению из переменных окружения.
  2. Напишите Dockerfile и .dockerignore.
  3. Создайте docker-compose.yml для локальной разработки с томами и переменными.
  4. Добавьте healthchecks и проверку готовности сервисов.
  5. Настройте CI для сборки и публикации образов в реестр.

Полезные шаблоны и сниппеты

.env (пример):

DATABASE_HOST=db
DATABASE_PORT=5432
DATABASE_USER=testUser
DATABASE_PASSWORD=mypassword123

.dockerignore (пример уже показан выше).

Multi-stage Dockerfile для продакшена — был приведён ранее.

Команды для работы с Compose:

docker compose up -d    # запустить в фоне
docker compose down     # остановить и удалить контейнеры
docker compose logs -f  # смотреть логи

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

  • Образ: неизменяемый артефакт, из которого создаётся контейнер.
  • Контейнер: выполняемый экземпляр образа с изолированной средой.
  • Volume: постоянное хранилище данных Docker, независимое от жизненного цикла контейнера.
  • Tag: метка образа в реестре.

Итог и рекомендации

Контейнеризация с Docker и Docker Compose упрощает разработку и развёртывание многосервисных приложений. Для разработки используйте Compose с томами и sync-файлами, а для продакшена — многоступенчатые сборки, управление секретами и управляемые БД при необходимости. Всегда тестируйте ожидание готовности зависимостей и добавляйте healthcheck’и.

Важно: рассмотрите альтернативы и ограничения — не всё подходит под контейнеры «из коробки». Для критичных к производительности систем или для сложных аппаратных зависимостей планируйте архитектуру заранее.

Ключевые ссылки и действия:

Поделиться: 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 быстро