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

“Работает на моём компьютере…” — шуточная фраза разработчиков точно отражает проблему: среда разработки отличается от продакшена. Контейнеризация устраняет эту проблему, упаковывая приложение с нужными зависимостями в единый образ.
В этом материале вы получите понятную пошаговую инструкцию по развёртыванию Nest.js приложения с базой PostgreSQL в двух контейнерах через Docker Compose, а также рекомендации по безопасности, тестированию и публикации образа в Docker Hub.
Что такое Docker и Docker Compose
Docker — открытая платформа для контейнеризации: вы создаёте образы, которые включают приложение и его зависимости. Эти образы запускаются как изолированные контейнеры. Контейнеры даёт предсказуемое поведение приложения в разных средах.
Docker Compose — инструмент для определения и управления многоконтейнерными приложениями. Если ваше приложение состоит из нескольких сервисов (веб-сервер, БД, очередь и т.д.), Compose позволяет описать их в одном файле и запускать как единое целое.
Важно: перед началом установите Docker Desktop и проверьте системные требования в официальной документации.
Что вы получите в руководстве
- Готовый Dockerfile для Nest.js
- docker-compose.yml с контейнером PostgreSQL
- Настройка TypeORM через .env
- Советы по безопасности и тестированию
- Шаги для загрузки образа в Docker Hub
Подготовка проекта Nest.js
Это руководство создаёт два контейнера: сервер с Nest.js и контейнер PostgreSQL.
Установите CLI Nest.js:
npm i -g @nestjs/cliСоздайте новый проект:
nest new docker-nest-appПри создании выберите менеджер пакетов (в примере — npm). Затем перейдите в папку проекта и запустите dev-сервер:
cd docker-nest-app
npm run startМодуль базы данных
Установите зависимости для PostgreSQL и TypeORM:
npm install pg typeorm @nestjs/typeorm @nestjs/configВ корне проекта создайте файл .env и добавьте параметры подключения к базе данных:
DATABASE_HOST="db"
DATABASE_PORT=5432
DATABASE_USER="testUser"
DATABASE_PASSWORD="mypassword123"Создайте модуль базы данных:
nest g module databaseОткройте файл database/database.module.ts и добавьте конфигурацию TypeORM:
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 {} Пояснение: TypeOrmModule.forRootAsync даёт возможность читать значения из .env через ConfigService и подставлять их при старте приложения.
Обновление AppModule
Добавьте DatabaseModule и настройку ConfigModule в src/app.module.ts:
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 {}Dockerfile для Nest.js
Создайте в корне проекта файл 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" ]Разбор команд:
- FROM — базовый образ Node.js (alpine для компактного размера).
- WORKDIR — рабочая директория в контейнере.
- COPY package*.json ./ — копирование package.json и package-lock.json для установки зависимостей.
- RUN npm install — установка зависимостей внутри образа.
- COPY . . — копирование исходников приложения.
- RUN npm run build — компиляция TypeScript в JavaScript (выход в dist).
- CMD — команда по умолчанию; здесь запущен dev режим.
Примечание: для production лучше запускать компилированный dist с node, а не start:dev. В dev режиме контейнер удобен для локальной разработки.
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:Объяснение: Compose описывает два сервиса: server (строится из Dockerfile) и db (использует официальный образ postgres). Volumes сохраняют данные PostgreSQL между запусками.
Запуск контейнеров
Соберите и запустите стек командой:
docker compose upПосле успешного запуска в логе вы увидите информацию о старте PostgreSQL и запуске Nest.js сервера на порту 3000.
Теперь можно продолжать разработку: добавлять сущности, репозитории и REST-контроллеры для CRUD.
Публикация образа в Docker Hub
Чтобы распределять образ через Docker Hub, выполните следующие шаги.
- Зарегистрируйтесь в Docker Hub и создайте репозиторий (можно публичный или приватный).
- Войдите в Docker из терминала:
docker login- Пометьте образ тегом в формате <ваш_пользователь>/<репозиторий>:
docker tag / - Отправьте образ в Docker Hub:
docker push / После этого любой пользователь с доступом сможет загрузить образ через docker pull.
Практические советы и лучшие практики
- Используйте .env для конфиденциальных данных, но не храните его в публичном репозитории.
- Для production: используйте multi-stage Dockerfile, чтобы исключить dev-зависимости и уменьшить размер образа.
- Старайтесь фиксировать версии образов и зависимостей (node:16.3.0-alpine3.13 → node:16-alpine).
- Не запускайте контейнеры от root-пользователя внутри образа — добавьте непользовательского юзера.
- Резервируйте volume для данных БД и бэкапов.
Безопасность и конфиденциальность
- Храните секреты в безопасном хранилище (Vault, AWS Secrets Manager, Docker Secrets), а не в .env в репозитории.
- Ограничьте сетевой доступ к базе данных: в Docker Compose можно настроить сети и включать контейнеры только в нужные сети.
- Не публикуйте образы с секретами в Docker Hub.
- Для соответствия требованиям GDPR: минимизируйте хранение персональных данных в контейнерах, шифруйте данные на уровне БД.
Тестирование и критерии приёмки
Критерии приёмки для рабочего развёртывания:
- Контейнер server отвечает на / (или на health endpoint) с 200 за < 5 с.
- Приложение успешно подключается к PostgreSQL и может выполнить простейший CRUD.
- Volume базы сохранён после перезапуска контейнеров.
- Логи приложения сохраняются и доступны (через docker logs или централизованную систему).
Минимальные тесты (локально):
- docker compose up
- Проверить доступность http://localhost:3000
- Выполнить HTTP-запросы к API и убедиться в корректности ответов
- Остановить контейнеры, удалить server, оставить volume и снова поднять — данные должны сохраниться
Когда контейнеризация не подходит (контрпримеры)
- Если приложение зависит от аппаратного ускорения (например, GPU) и нет соответствующих драйверов в контейнере.
- Если требуется тесная интеграция с хостовой ОС (специальные устройства), контейнер может усложнить работу.
- Для очень простых статических сайтов контейнеризация может быть избыточной.
Альтернативы и эволюция инфраструктуры
- Podman — альтернатива Docker без демона, совместимая с CLI Docker.
- Kubernetes — следующий шаг после Docker Compose для оркестрации множества реплик и автоматического масштабирования.
- Platform-as-a-Service (Heroku, Render) — упрощают деплой без управления контейнерами вручную.
Ментальная модель: Docker — упаковщик + изолятор; Compose — менеджер для локальной мультисервисной среды; Kubernetes — оркестратор для production-кластеров.
Mini-методология: от локального прототипа к production
- Локальный прототип с docker-compose и dev-режимом.
- Перевести Dockerfile в multi-stage для production.
- Обеспечить CI: сборка образа и автотесты в pipeline.
- Публикация образа в реестр (Docker Hub/registry).
- Развёртывание в оркестраторе (K8s) или PaaS.
Рольные чек-листы
Разработчик:
- Локально запускает docker compose up
- Пишет unit- и интеграционные тесты
- Не хранит секреты в репозитории
DevOps-инженер:
- Создаёт CI для сборки и проверки образов
- Настраивает реестр образов и политики тегирования
- Настраивает мониторинг и backup volume
Тестировщик:
- Проверяет подключение к БД при рестарте контейнера
- Тестирует сценарии отказа (упал БД → приложение корректно логирует)
Примеры команд для отладки
- Просмотр логов сервиса:
docker compose logs -f server- Выполнение команд внутри контейнера:
docker compose exec server sh- Просмотр запущенных контейнеров:
docker psСценарий отката (грубая инструкция)
- Остановить новые контейнеры: docker compose down
- Откатить образ на ранее протестированный тег: docker pull
/ :stable - Обновить docker-compose.yml на нужный тег и поднять стек
- Проверить health endpoint и логи
Короткая аннотация для анонса
Запуск Nest.js с PostgreSQL в Docker Compose: быстрое практическое руководство по созданию Dockerfile, подключению TypeORM, публикации образа и рекомендациям по безопасности и тестированию.
Куда двигаться дальше
- Перевести сборку в CI (GitHub Actions/GitLab CI) и автоматически публиковать образы.
- Изучить Kubernetes и Helm-чарты для production-окружения.
- Добавить supervisord/entrypoint-скрипты для миграций БД при старте контейнера.
Резюме
Использование Docker и Docker Compose упрощает переносимость Nest.js приложений между машинами и средами. Правильная конфигурация Dockerfile, docker-compose.yml и безопасное хранение секретов — ключ к стабильному и масштабируемому развёртыванию.
Important: для production переключитесь на multi-stage билды, безопасное хранение секретов и оркестрацию (Kubernetes) при необходимости.
Критерии приёмки выше помогут убедиться, что базовый стек работает корректно и готов к дальнейшей автоматизации.
Похожие материалы
Стрим Netflix в Discord — полный гид
ИИ-озвученные аудиокниги: преимущества и риски
Как запускать и вести email‑рассылку
Включение Tamper Protection в Microsoft Defender
Как вернуть Проводник на панель задач в Windows 11