
Цикл «сервер на VPS»: настройка конфигурация Nginx и Docker
Настройка сервера Nginx и конфигурации Docker
Развёртывание веб-приложений на одном сервере требует правильной изоляции сервисов и настройки обратного прокси. В этой статье мы разберём практический пример деплоя Next.js приложения с PostgreSQL через Docker и Nginx. Вы узнаете, как настроить multi-stage сборку для оптимизации размера образа, организовать коммуникацию между контейнерами и правильно сконфигурировать Nginx для обработки трафика нескольких доменов.
Docker конфиг catshredias-blog
Первым делом стоит прочитать статью https://habr.com/ru/companies/netologyru/articles/967546/, в ней описывается архитектура технологии и примеры использования для новичков.
На примере конфигурации сайта cathshredias-blog (https://catshredia.ru/) я опишу основные моменты, которые я использовал в Docker.
- docker-compose.yml - основной файл, в котором описаны образы и их свойства:
services:
db:
image: postgres:16-alpine
container_name: portfolio-db
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB:-portfolio_db}
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
ports:
- "127.0.0.1:55433:5432"
volumes:
- portfolio_pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
web:
build:
context: .
dockerfile: Dockerfile
args:
NPM_REGISTRY: ${NPM_REGISTRY:-https://registry.npmjs.org}
container_name: portfolio-web
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "127.0.0.1:3000:3000"
env_file:
- .env
environment:
DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@db:5432/${POSTGRES_DB:-portfolio_db}
AUTH_SECRET: ${AUTH_SECRET}
AUTH_URL: ${AUTH_URL:-http://localhost:3000}
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-http://localhost:3000}
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@catshredia.ru}
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-changeme}
CRON_SECRET: ${CRON_SECRET:-}
TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN:-}
TELEGRAM_CHAT_ID: ${TELEGRAM_CHAT_ID:-}
TELEGRAM_PROXY_URL: ${TELEGRAM_PROXY_URL:-}
TURNSTILE_SECRET_KEY: ${TURNSTILE_SECRET_KEY:-}
volumes:
- uploads:/app/uploads
# === образы миграции и засеивания ===
# указываем volume Для БД и загрузок пользователей
volumes:
portfolio_pg_data:
uploads:
- Dockerfile - файл, который гарантирует масштабируемость и переносимость образов:
# записываем node как базовый образ
FROM node:22-alpine AS base
# устанавливаем пакет совместимости через apk (пакетный менеджер)
RUN apk add --no-cache libc6-compat
WORKDIR /app #рабочая директория
# сохраняем node образ в другой
FROM base AS deps
# используем зеркало во время установки npm ci
ARG NPM_REGISTRY=https://registry.npmjs.org
COPY package.json package-lock.json ./
RUN npm config set registry "${NPM_REGISTRY}" && npm ci
# создаем образ, который будем билдить и вносим в него зависимости из deps
FROM base AS builder
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npx prisma generate
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# создаем образ для запуска, копируем зависимости из builder, устанавливаем порты и точки входа
FROM base AS runner
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs
WORKDIR /app
COPY --from=builder /app/public ./public
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY docker-entrypoint.sh /app/docker-entrypoint.sh
RUN mkdir -p /app/uploads && chown nextjs:nodejs /app/uploads \
&& chmod +x /app/docker-entrypoint.sh
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME=0.0.0.0
ENTRYPOINT ["/app/docker-entrypoint.sh"]
Также добавим файл с точками входа:
#!/bin/sh
set -e
exec node .next/standalone/server.js
Обращу внимание на RUN npm config set registry "${NPM_REGISTRY}" && npm ci - настройка зеркала для скачивания через npm ci (для ру региона) и работы в условиях недоступности этих ресурсов.
- .dockerignore файл - нужен для внесения директорий и файлов в список исключений для Docker (чтобы лишние файлы не попадали в обработку Docker).
Настройка конфигурации: 2 сайта - один сервер
Если существует несколько небольших проектов (не потребляющих много ресурсов, возможно их размещение на одном сервере. Далее, инструкция по настройке такой конфигурации.
У нас уже есть две конфигурации Docker, из них мы берем порты для внешнего трафика, подготовим nginx конфигурации
**/etc/nginx/sites-available/example.ru:**
вместо 3000 подставьте порт из docker конфига
server {
listen 80;
server_name example.ru;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
**/etc/nginx/sites-available/news.example.ru:**
вместо 8080 подставьте порт из docker конфига
server {
listen 80;
server_name news.example.ru;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# дополнительно пример конфига для хабов (например SignalR)
location /hubs/ {
proxy_pass http://127.0.0.1:8080/hubs/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
- Активируем конфиги
После создания файлов конфигурации необходимо создать символические ссылки в директорию sites-enabled и перезагрузить Nginx:
sudo ln -s /etc/nginx/sites-available/example.ru /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/news.example.ru /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Настройка HTTPS через Let's Encrypt
В 2026 году работа сайтов только по HTTP считается небезопасной. Браузеры помечают такие сайты как "Not Secure", а поисковые системы понижают их в выдаче. Рассмотрим настройку бесплатных SSL-сертификатов через Certbot.
- установим Certbot и для каждого выдадим сертификаты
sudo apt update
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.ru
sudo certbot --nginx -d news.example.ru
Certbot автоматически:
- Получит SSL-сертификат от Let's Encrypt
- Обновит конфигурацию Nginx
- Настроит редирект с HTTP на HTTPS
- Добавит задачу в cron для автоматического обновления сертификатов Также возможно создание сертификатов через конфиг:
# Редирект с HTTP на HTTPS
server {
listen 80;
server_name example.ru;
return 301 https://$host$request_uri;
}
# Основной HTTPS блок
server {
listen 443 ssl http2;
server_name example.ru;
# Пути к сертификатам (автоматически создаются Certbot)
ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
# Дополнительные настройки безопасности SSL
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Проверка работы
# Тест конфигурации Nginx
sudo nginx -t
# Перезагрузка Nginx
sudo systemctl reload nginx
# Проверка статуса сертификата
sudo certbot certificates
# Онлайн проверка SSL
# https://www.ssllabs.com/ssltest/
Мы рассмотрели базовую архитектуру деплоя современного веб-приложения. Ключевые моменты: использование multi-stage Dockerfile для уменьшения размера образа, healthchecks для контроля состояния сервисов, и правильная настройка Nginx как reverse proxy. Для production-окружения обязательно добавьте HTTPS, мониторинг ресурсов и автоматические бэкапы базы данных. Помните: безопасность и отказоустойчивость важнее скорости развёртывания.