Docker Compose шаблоны для веб-проекта: Nginx + App + PostgreSQL + Redis
Готовые docker-compose.yml для типичных стеков: Node.js, Python/Django, PHP. Настройка healthcheck, volumes и production-оптимизации.
Docker Compose для типичного веб-стека: Nginx (reverse proxy + SSL), приложение (Node.js/Python/PHP), PostgreSQL (СУБД), Redis (кэш + сессии). Ключевые правила: именованные volumes для данных, healthcheck для зависимостей, ограничения ресурсов (deploy.resources), .env для секретов.
- Docker Compose — стандарт для деплоя веб-приложений на одном сервере. Один файл описывает весь стек.
- Всегда используйте healthcheck для СУБД — приложение не должно стартовать раньше базы.
- Volumes для данных PostgreSQL — обязательно именованные, не bind-mount. Иначе потеряете данные при docker compose down.
- Nginx как reverse proxy — SSL termination, статика и кэширование без нагрузки на приложение.
Универсальный шаблон: Node.js + PostgreSQL + Redis + Nginx
Этот шаблон покрывает 80% веб-проектов. Замените образ приложения на свой — и всё работает:
# docker-compose.yml
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./certbot/conf:/etc/letsencrypt:ro
depends_on:
app:
condition: service_healthy
restart: always
app:
build: .
environment:
- DATABASE_URL=postgres://app:secret@db:5432/myapp
- REDIS_URL=redis://redis:6379
- NODE_ENV=production
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 10s
timeout: 5s
retries: 3
restart: always
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d myapp"]
interval: 5s
timeout: 3s
retries: 5
restart: always
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 3
restart: always
volumes:
pgdata:Nginx конфигурация для reverse proxy
Nginx принимает HTTP-трафик и проксирует его в контейнер приложения:
# nginx.conf
upstream app {
server app:3000;
}
server {
listen 80;
server_name example.com;
# Статика (если есть)
location /static/ {
alias /var/www/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Проксирование в приложение
location / {
proxy_pass http://app;
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;
}
}Типичные ошибки и как их избежать
Ошибка 1: bind-mount вместо named volume для БД. docker compose down -v удалит ваши данные, если PostgreSQL использует bind-mount. Всегда — именованные volumes (pgdata: в примере).
Ошибка 2: нет healthcheck для зависимостей. Без healthcheck приложение стартует раньше PostgreSQL и падает с "connection refused". depends_on без condition: service_healthy — просто ждёт старта контейнера, не готовности.
Ошибка 3: пароли в docker-compose.yml. Используйте .env файл и переменные ${DB_PASSWORD}. Добавьте .env в .gitignore.
Ошибка 4: restart: always без ограничений ресурсов. Утечка памяти в приложении может убить весь сервер. Добавьте deploy.resources.limits.memory: 512m.
Проверенные серверы от надежных провайдеров
Timeweb Cloud
Cloud Start
CPU
1 ядер • 3.3 ГГц
RAM
1 ГБ
Диск
15 ГБ NVMe
Канал
200 Мбит/с
299 ₽/мес
Selectel
Cloud Lite 1
CPU
1 ядер • 2.6 ГГц
RAM
1 ГБ
Диск
10 ГБ SSD
Канал
200 Мбит/с
550 ₽/мес
Часто задаваемые вопросы (FAQ)
Как обновить приложение без даунтайма?
docker compose build app && docker compose up -d --no-deps app. Это пересобирает только контейнер приложения и перезапускает его. СУБД и Redis не трогаются.
Как добавить SSL (HTTPS)?
Используйте Certbot: docker compose run certbot certonly --webroot -w /var/www/certbot -d example.com. Или Nginx Proxy Manager — GUI для управления SSL-сертификатами.