Микросервисы на одном VPS через docker-compose
Не всякой микросервисной архитектуре нужен Kubernetes. На старте несколько сервисов прекрасно живут на одном VPS под docker-compose. Соберём стек с reverse proxy, внутренней сетью, healthcheck и централизованными логами.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Когда достаточно одного VPS
Kubernetes оправдан, когда сервисов десятки и нужен автоскейлинг между нодами. Пока их 3–8 и трафик умеренный, docker-compose на одном сервере проще в эксплуатации и дешевле: один VPS вместо кластера.
compose даёт всё нужное: изолированные контейнеры, общую сеть по именам, healthcheck, лимиты ресурсов и одну команду для подъёма всего стека.
Несколько сервисов делят одно ядро и диск, поэтому важна производительность на ядро. AMD EPYC + NVMe у MAATRIX держит и БД, и очередь, и веб одновременно без деградации отклика. Именно IO-latency обычно становится первым узким местом при уплотнении сервисов на одну машину, и здесь NVMe даёт запас, которого нет у SATA-виртуалок.
Важно и то, что миграция на Kubernetes позже пройдёт безболезненно: те же образы, те же переменные окружения, те же healthcheck. docker-compose — это не тупик, а естественная первая ступень, с которой вы в любой момент шагнёте в k3s, когда сервисов станет по-настоящему много.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS для микросервисовСтруктура стека
Возьмём типичный набор: reverse proxy (Caddy), два бэкенд-сервиса (api, worker), база (Postgres) и брокер (Redis). Все — в одной compose-сети, наружу торчит только прокси.
services:
proxy:
image: caddy:2-alpine
ports: [ "80:80", "443:443" ]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
depends_on: [ api ]
api:
build: ./api
environment:
DATABASE_URL: postgres://app:secret@db:5432/app
REDIS_URL: redis://cache:6379
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
retries: 3
depends_on:
db: { condition: service_healthy }
worker:
build: ./api
command: python worker.py
depends_on: [ cache, db ]
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
volumes: [ pgdata:/var/lib/postgresql/data ]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
retries: 5
cache:
image: redis:7-alpine
volumes:
pgdata:
Сеть и обращение по именам
compose автоматически создаёт общую сеть, и сервисы видят друг друга по имени. Внутри контейнера api адрес базы — просто db:5432, брокера — cache:6379. Никаких IP руками прописывать не нужно.
Наружу выставлен только proxy. Порты db и cache не публикуйте через ports — иначе база окажется в открытом интернете. Доступ к ней только изнутри сети compose.
Reverse proxy Caddy автоматически получает Let's Encrypt-сертификат. Минимальный Caddyfile:
api.example.com {
reverse_proxy api:8000
}
Запуск, логи и масштабирование
Поднимаем весь стек и смотрим статус healthcheck:
docker compose up -d
docker compose ps
docker compose logs -f api
Отдельный сервис можно масштабировать в несколько реплик — прокси распределит нагрузку, если сервис stateless:
docker compose up -d --scale worker=3
Ограничьте ресурсы, чтобы один сервис не съел весь VPS. В compose это делается через deploy.resources.limits:
deploy:
resources:
limits:
cpus: "0.50"
memory: 256M
Лимит памяти особенно важен для сервисов с потенциальными утечками: контейнер, упёршийся в свой memory-лимит, будет перезапущен, а не утянет за собой весь VPS. Это дешёвая страховка, которую часто забывают выставить.
Частые ошибки
- Сервис стартует раньше БД —
depends_onбезcondition: service_healthyне ждёт готовности, только запуска. Всегда добавляйте healthcheck базе. - БД доступна из интернета — опубликовали порт 5432 наружу. Убирайте
portsу внутренних сервисов. - Диск забит логами — настройте ротацию через
logging.options.max-size. - Один сервис положил сервер — нет лимитов CPU/RAM, утечка памяти съела весь VPS.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS для микросервисовОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Сколько сервисов потянет один VPS?
Зависит от нагрузки, но 5–10 лёгких сервисов на VPS с 4 ГБ RAM работают комфортно. Следите за суммарным потреблением памяти.
Как обновить один сервис без остановки остальных?
Выполните docker compose up -d --no-deps --build api — пересоберётся и перезапустится только указанный сервис.
Нужен ли отдельный сервер под базу?
На старте нет. Когда БД станет узким местом, вынесете её на отдельный VPS, изменив DATABASE_URL.