Контейнеры стали стандартным способом доставки приложений в production: одинаковое окружение на ноутбуке и на сервере, быстрый откат версий, изоляция зависимостей. В 2026 году деплой Docker на VPS — must-have навык для backend-разработчика на Python, Node.js, Go или PHP. Это дешевле managed Kubernetes на старте и понятнее, чем «голый» systemd с десятком venv. В этом руководстве — полный цикл: от чистого VPS до работающего приложения за reverse proxy с HTTPS, плюс best practices для эксплуатации.
Когда Docker на VPS — правильный выбор
- Несколько сервисов: API + worker + Redis + PostgreSQL.
- Нужна воспроизводимость деплоя из CI/CD.
- Команда без выделенного DevOps, но с Dockerfile в репозитории.
- План миграции в Kubernetes позже — Docker Compose как промежуточный этап.
Когда Docker избыточен: один простой скрипт или static site — достаточно nginx и systemd. Для Java-стека те же идеи развиты в статье про контейнеризацию Java и Kubernetes.
Что понадобится на VPS
- Ubuntu 22.04/24.04 LTS (или Debian 12).
- Минимум 2 GB RAM для app + БД в Compose; 1 GB — только для одного лёгкого контейнера.
- 20+ GB SSD/NVMe.
- Домен с A-записью на IP сервера.
- SSH-доступ по ключу.
VPS можно взять у Beget, Timeweb или другого провайдера. Для связки с другими материалами prizraks.ru: Beget VPS через prizraks.ru/go/beget.
Шаг 1: Базовая настройка сервера
После первого входа:
- Создайте пользователя с sudo, отключите root-login по SSH.
- Настройте ufw:
allow OpenSSH,allow 80,allow 443,enable. - Обновите пакеты:
apt update && apt upgrade -y. - Установите fail2ban (опционально, но рекомендуется).
- Задайте timezone:
timedatectl set-timezone Europe/Moscow.
Шаг 2: Установка Docker Engine и Compose
Официальный способ — репозиторий Docker (не путать с устаревшим docker.io из дистрибутива без compose plugin):
- Установите Docker CE, containerd, docker-buildx-plugin, docker-compose-plugin.
- Добавьте пользователя в группу
docker, перелогиньтесь. - Проверка:
docker run hello-world,docker compose version.
В 2026 используйте Compose V2 (docker compose, не отдельный бинарник docker-compose v1).
Шаг 3: Структура проекта
Типичный репозиторий:
Dockerfile— multi-stage для Python/Node (build → slim runtime).docker-compose.yml— сервисы app, db, redis, nginx..env— секреты (не в Git),.env.example— шаблон.nginx/conf.d/app.conf— reverse proxy.
Пример multi-stage Dockerfile (Python/FastAPI)
Stage build: установка зависимостей в venv. Stage production: копирование venv и кода, non-root user, CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"].
docker-compose.yml
app— build context, env_file, depends_on db/redis.db— postgres:16-alpine, volume для данных.redis— redis:7-alpine.nginx— ports 80:80, 443:443, volumes config + certbot.
Шаг 4: Первый запуск на VPS
- Клонировать репозиторий:
git clone ... /opt/myapp - Скопировать
.env.example→.env, заполнить пароли. docker compose builddocker compose up -ddocker compose ps— все healthy.- Логи:
docker compose logs -f app
Для Telegram-бота в контейнере webhook проксируется так же, как без Docker — см. деплой Telegram-бота для логики webhook; здесь фокус на контейнерной обёртке.
Шаг 5: Nginx и SSL (Let’s Encrypt)
Вариант A: nginx на хосте
Nginx установлен на VPS, проксирует на 127.0.0.1:PORT, который проброшен из compose. Certbot —nginx на хосте.
Вариант B: nginx в контейнере + certbot
Используйте nginx-proxy + acme-companion или traefik с automatic HTTPS. Для простоты часто nginx на хосте + compose только для app/db.
После SSL проверьте редирект HTTP→HTTPS и заголовки HSTS для production.
Шаг 6: Миграции и фоновые worker’ы
- Миграции БД:
docker compose exec app alembic upgrade headилиpython manage.py migrate. - Celery worker — отдельный сервис в compose с тем же image, другой command.
- Не запускайте migrate при каждом старте контейнера в production без контроля — лучше явно из CI/CD или deploy script.
Сравнение подходов к деплою Docker на VPS
| Подход | Сложность | Zero-downtime | Кому подходит |
|---|---|---|---|
| docker compose up -d вручную | Низкая | Нет (краткий простой) | Solo, staging, MVP |
| Deploy script + git pull + compose | Средняя | Минимальный простой | Малые команды |
| Watchtower / auto-pull | Низкая | Нет | Небольшие pet-projects (осторожно в prod) |
| GitHub Actions SSH deploy | Средняя | Частично (rolling вручную) | Регулярные релизы |
| Blue-green два compose project | Высокая | Да | Критичный uptime |
| Kubernetes | Очень высокая | Да | Масштаб, many services |
CI/CD: GitHub Actions → VPS
Типовой pipeline:
- Push в
main→ test job (pytest, lint). - Build Docker image → push в GitHub Container Registry или Docker Hub.
- SSH на VPS:
docker compose pull && docker compose up -d. - Опционально: health check curl на /health.
Секреты: SSH private key, registry token — в GitHub Secrets. На VPS не храните пароли registry в plain text.
Безопасность Docker на VPS
- Не запускайте контейнеры от root внутри — USER в Dockerfile.
- Не публикуйте порты БД наружу (
5432:5432только на localhost или internal network). - Docker socket (
/var/run/docker.sock) — не монтировать в app-контейнер без крайней нужды. - Регулярно
docker compose pullдля base images с патчами. - Scan образов: Trivy, Docker Scout.
- Limit resources в compose:
mem_limit,cpus. - Read-only filesystem где возможно, cap_drop ALL.
Логи, мониторинг, бэкапы
Логи
json-file driver с rotation (max-size, max-file). Централизация: Loki, или простой vector → файл. Application logs в stdout/stderr — twelve-factor way.
Мониторинг
Prometheus node_exporter на хосте, cAdvisor для контейнеров, Uptime Kuma для HTTP checks. Алерты в Telegram админу — пересекается с практикой из bot-гайдов на prizraks.ru.
Бэкапы
- Volume PostgreSQL: nightly
pg_dumpв S3 или второй сервер. - Конфиг nginx и
.env— encrypted backup. - Тест восстановления раз в квартал — backup без restore бесполезен.
Оптимизация образов
- Multi-stage build — маленький финальный слой.
- .dockerignore — не тащить .git, tests, __pycache__.
- Pin версий base image (
python:3.12-slim-bookworm). - Кэш слоёв: сначала COPY requirements, pip install, потом код.
- Alpine vs slim — slim проще для Python с native wheels.
ML-сервисы с GPU (YOLO inference) на VPS без GPU используют CPU-образы; см. YOLO11 — модель в контейнере, но железо должно соответствовать нагрузке.
Типичные проблемы и решения
| Проблема | Причина | Решение |
|---|---|---|
| 502 Bad Gateway | App не слушает или упал | logs app, проверить bind 0.0.0.0, healthcheck |
| Cannot connect to db | Неверный host (db vs localhost) |
В compose использовать service name как hostname |
| Permission denied volume | UID mismatch | chown или user в Dockerfile совпадает с volume |
| Диск заполнен | Старые образы | docker system prune -a (осторожно), log rotation |
| OOM killed | Мало RAM | Увеличить VPS или limits, отделить БД |
Обновление приложения без простоя (упрощённо)
- Build новый image с тегом версии.
docker compose up -d --no-deps app— пересоздать только app.- Health check OK — готово; fail — откат image tag предыдущий.
Для БД backward-compatible migrations сначала, deploy app потом — expand/contract pattern.
Docker Compose vs Swarm vs Kubernetes
На одном VPS в 2026 Compose покрывает 80% задач SMB. Swarm почти не используют greenfield. Kubernetes оправдан при нескольких нодах, autoscaling, service mesh — иначе overhead съест бюджет. Путь роста: Compose на VPS → managed k8s (или self-hosted) при доказанной необходимости.
Связь с обучением и архитектурой
Контейнеры не отменяют fundamentals: структура кода, ООП, тесты. Основы ООП помогают проектировать сервисы, которые удобно упаковывать в образы. Pet-project с Dockerfile в GitHub — сильный сигнал employer’у.
Чеклист production-ready деплоя
- Dockerfile multi-stage, non-root user
- compose с healthcheck для app и db
- .env вне Git, secrets в CI
- nginx + HTTPS, автообновление cert
- Миграции под контролем deploy script
- Бэкапы БД и тест restore
- Мониторинг uptime и disk
- Документированный rollback
Пример docker-compose для Python API + PostgreSQL
Концептуальная структура (адаптируйте под проект):
- services.app — build: ., ports не публиковать наружу, только expose 8000 в internal network.
- services.db — image postgres:16-alpine, environment POSTGRES_PASSWORD из env, volume pgdata.
- services.redis — для cache/queue если нужно.
- networks — default bridge или явная internal network.
На хосте nginx проксирует 443 → app:8000 через published port только на 127.0.0.1:8000:8000 — так БД не светится в интернет.
Watchtower и автоматические обновления: осторожно
Watchtower тянет новые образы и перезапускает контейнеры — удобно для homelab, рискованно для production без staging. Если используете — pin digest образа, тестируйте в CI, включайте уведомления о перезапуске. Предсказуемее deploy по webhook из GitHub Actions.
Несколько окружений на одном VPS
Staging и production: два каталога /opt/app-staging, /opt/app-prod, разные compose project name (docker compose -p staging), разные env и subdomain. Общий nginx vhost маршрутизирует по Host header. Экономия на втором VPS, но blast radius выше — ошибка в nginx config заденет оба.
SELinux и AppArmor на Ubuntu
На stock Ubuntu обычно не мешают Docker. Если включён hardening — проверьте профили для container runtime. Типичная ошибка после hardening — nginx не может connect к upstream; смотрите audit.log.
Связка Docker на VPS и Beget для смешанных проектов
Частая схема: Laravel или legacy PHP на managed/shared Beget, новый Python microservice в Docker на VPS. DNS: api.domain.ru → VPS, domain.ru → shared. SSL на обоих. Единый мониторинг Uptime Kuma на VPS. Beget для legacy: prizraks.ru/go/beget.
Часто задаваемые вопросы
Как деплоить Docker на VPS в 2026?
Установите Docker Engine и Compose plugin, клонируйте репозиторий с Dockerfile и compose, настройте .env, docker compose up -d, nginx + Certbot для HTTPS.
Нужен ли Kubernetes для одного приложения?
Нет. Docker Compose на VPS достаточно до появления требований к autoscaling и multi-node.
Где хостить VPS для Docker?
Любой провайдер с 2+ GB RAM: Beget, Timeweb, Selectel. Beget: https://prizraks.ru/go/beget.
Как обновить контейнеры?
git pull, docker compose build --pull, docker compose up -d. В CI — push image и pull на сервере.
Безопасно ли хранить .env на сервере?
Да, с правами 600 и пользователем deploy. Лучше Docker secrets или vault при росте команды.
PostgreSQL в Docker для production?
Допустимо на SMB VPS с бэкапами и named volume. При высоких SLA — managed DB провайдера.
Как деплоить Python-бота в Docker?
Образ с aiogram/PTB, webhook через nginx, переменные BOT_TOKEN в env. Логика бота: гайд на prizraks.ru.
На prizraks.ru мы деплоим Docker-приложения для клиентов: CRM, API, боты и пайплайны автоматизации. Нужен аудит текущего VPS или настройка CI/CD под ключ — напишите через сайт, разберём стек и соберём воспроизводимый деплой.
Для Python, PHP, ботов и pet-проектов мы рекомендуем Beget — SSH, Python, cron и поддержка 24/7 от 150 ₽/мес.
Подборка онлайн-курсов для разработчиков — Python, Java, веб и DevOps.
Автоматизация, CRM, Telegram-боты, деплой и техподдержка 24/7.
Телефон: 8 918 532 81 08 · Заказать услугу
Статья может содержать партнёрские ссылки. Это не влияет на стоимость для вас, но помогает развивать блог.
