Руководства

Docker на VPS: сколько ресурсов нужно контейнерам

Docker на VPS: сколько ресурсов нужно контейнерам

Docker на VPS давно перестал быть экзотикой: в контейнерах разворачивают и одиночного Telegram-бота, и связку из веб-сервера, приложения, базы, очереди и мониторинга. Работает это хорошо, но у контейнеров есть свои расходы по памяти и диску и несколько ловушек, о которых узнают уже после аварии, — самая неприятная из них открывает порты базы данных в интернет в обход firewall. Разберём, сколько ресурсов закладывать, какой тариф брать под типовые связки и что настроить сразу после установки.

Что должен уметь сервер

Docker нужна полноценная виртуализация, где у машины своё ядро, — KVM. На контейнерной виртуализации (OpenVZ, LXC) ядро общее с соседями, и Docker там либо не запускается, либо работает с ограничениями. Это первое, что стоит проверить перед покупкой. У провайдера, тарифы которого мы отслеживаем, на страницах каталога указана виртуализация KVM, так что Docker и docker compose работают без плясок. Подробнее о типах виртуализации — в статье «VPS и VDS: в чём разница».

Что контейнеры дают, а что нет

Дают:

  • Одинаковое окружение на машине разработчика и на сервере — оно описано в файле, а не собрано руками.
  • Простое обновление и откат: docker compose pull && docker compose up -d, а если что-то пошло не так — вернуть предыдущий тег образа.
  • Изоляцию зависимостей: два проекта с разными версиями PHP, Node или Python спокойно живут на одном сервере.
  • Переезд за минуты: на новом сервере нужен только Docker, файл compose и данные томов.

Не дают:

  • Границу безопасности уровня отдельной машины. Ядро общее, и уязвимость в нём касается всех контейнеров сразу. Для разделения доверенного и чужого кода контейнера мало.
  • Скорости. Накладные расходы невелики, но медленный код в контейнере остаётся медленным.
  • Сохранности данных. Образ пересобирается, данные — нет. Тома нужно копировать так же, как обычные файлы и базы.

Сколько памяти занимают контейнеры

Сам демон Docker забирает 50–100 МБ. Дальше каждый контейнер несёт свой процесс и библиотеки. Ориентиры в спокойном режиме:

КонтейнерПамять
Nginx, Caddy, Traefik10–50 МБ
Redis для кэша10–100 МБ + объём данных
Бот или API на Python / Go30–200 МБ
Приложение на Node.js100–300 МБ
PHP-FPM с WordPress150–400 МБ
PostgreSQL100–400 МБ, больше под кэш данных
MySQL / MariaDB300–600 МБ
Prometheus + Grafana300–700 МБ

Сложите свою связку и добавьте 30% на пики и 300–400 МБ на систему. Как считать по компонентам в общем случае — в статье «Как выбрать тариф VPS».

Какой тариф под какую связку

Что запускаетеТарифЦена/мес
1–2 бота или небольшой APILite: 1 ядро, 1 ГБ, 20 ГБ$6
Сайт: прокси + приложение + базаStart: 2 ядра, 2 ГБ — впритык; Medium: 3 ядра, 4 ГБ — комфортно$10–20
Приложение + база + Redis + воркер очереди + проксиMedium–Premium: 4–8 ГБ$20–40
Несколько проектов или self-hosted инструменты (Gitea, Nextcloud, мониторинг)Premium–Elite: 8–16 ГБ$40–60

Цены — для Европы, России, Казахстана и Северной Америки. Отдельно про диск: каждый образ весит от 50 МБ до гигабайта, а старые версии копятся после каждого обновления. На 20 ГБ Lite это заканчивается быстрее, чем кажется, — закладывайте запас и настройте очистку (ниже).

Для контейнеров полезен NVMe: запуск, сборка и базы в томах много работают с файловой системой. NVMe стоит во всех тарифах Финляндии, Нидерландов и Чехии.

Medium в Финляндии, NVMe — $20/мес   Premium в Нидерландах, NVMe — $40/мес

Установка

Сначала базовая настройка сервера — пользователь, ключи, firewall, обновления: 10 шагов после покупки. Затем Docker из официального репозитория:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker deploy

После перелогина пользователь deploy сможет запускать docker без sudo. Учтите: членство в группе docker фактически равно root-доступу, поэтому давайте его только тем, кому доверяете как администратору.

Пять вещей, которые настроить сразу

1. Не открывать базу в интернет в обход firewall

Самая опасная ловушка. Docker сам пишет правила iptables, и порт, опубликованный как ports: - "5432:5432", становится доступен из интернета даже при включённом ufw с запретом этого порта. Именно так в сеть утекают базы с паролем по умолчанию.

Правило простое: наружу публикуется только обратный прокси на 80 и 443. Внутренние сервисы общаются по сети compose, без ports вовсе. Если порт нужен вам для отладки — привязывайте к localhost:

ports:
  - "127.0.0.1:5432:5432"

Проверить, что реально открыто наружу, можно с другой машины: nmap -Pn IP_СЕРВЕРА.

2. Ротация логов

По умолчанию логи контейнеров пишутся без ограничений и однажды съедают весь диск — одна из самых частых аварий на Docker-серверах. В /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" }
}

Затем sudo systemctl restart docker. Настройка действует на контейнеры, созданные после неё, — существующие пересоздайте через docker compose up -d --force-recreate.

3. Лимиты памяти и процессора

Без лимитов один контейнер с утечкой памяти может занять всю машину и уронить соседей, а ядро при нехватке памяти первым убьёт базу. В compose:

services:
  app:
    image: myapp:1.4
    mem_limit: 512m
    cpus: 1.0
    restart: unless-stopped

Лимит ставьте с запасом над обычным потреблением: смотрите реальные цифры в docker stats.

4. Автозапуск

restart: unless-stopped у каждого сервиса — и после перезагрузки сервера всё поднимется само. Без этого простой продлится до того момента, когда вы заметите.

5. Очистка

Старые образы, остановленные контейнеры и кэш сборки копятся гигабайтами. Раз в неделю по cron:

0 4 * * 0 docker system prune -af --filter "until=168h"

Флаг --volumes сюда не добавляйте: он удалит тома, не привязанные к контейнерам, — а среди них могут оказаться данные остановленного сервиса.

Бэкапы данных в контейнерах

Базу копируйте дампом изнутри контейнера, а не копированием файлов работающей базы:

docker exec db pg_dump -U app appdb | gzip > /var/backups/appdb.sql.gz
docker exec mysql mysqldump -u root -p"$PASS" --all-databases | gzip > /var/backups/mysql.sql.gz

Файловые тома — архивом через временный контейнер:

docker run --rm -v uploads:/data -v /var/backups:/backup alpine \
  tar czf /backup/uploads.tgz -C /data .

Дальше эти файлы забирает бэкап-сервер в другой стране. Как настроить так, чтобы взломщик не мог удалить копии, — в статье «Сервер для бэкапа».

Собирайте образы не на сервере

Сборка образа требовательна к процессору и диску: на Lite или Start она может занимать десятки минут и заметно тормозить работающие сервисы. Правильнее собирать образы в CI (GitHub Actions, GitLab CI) или на своём компьютере, отправлять в реестр, а на сервере делать только docker compose pull. Если собирать всё же приходится на сервере, упор будет в частоту процессора — здесь выигрывает HI-CPU на Ryzen.

Панель управления и Docker

Хостинговые панели вроде ISPmanager рассчитаны на собственную структуру конфигов и плохо уживаются с контейнерами, которые сами управляют портами и сетями. Если проект в Docker, обходитесь без панели или используйте интерфейс, сделанный для контейнеров, — например, Portainer. Подробнее о выборе — в статье «Панель или консоль».

Коротко

  • Docker нужна KVM-виртуализация — проверьте до покупки.
  • Считайте память по контейнерам: связка «прокси + приложение + база» комфортно живёт на 4 ГБ (Medium, $20).
  • Не публикуйте порты базы наружу: Docker обходит ufw. Внутренние сервисы — без ports или на 127.0.0.1.
  • Сразу настройте ротацию логов, лимиты памяти, restart: unless-stopped и еженедельную очистку.
  • Базы копируйте дампом, тома — архивом, и храните копии на другом сервере.
  • Образы собирайте в CI, на сервер — только pull.