CapRover — открытая PaaS-платформа, которая превращает один сервер с Docker в подобие Heroku: веб-панель, приложения в контейнерах, автоматические сертификаты, домены и базы данных в один клик. Данные и сборки остаются на вашей машине, а счёт не зависит от числа деплоев.
Материал рассчитан на администратора со знанием SSH и Docker: установка, деплой, тома, бэкап и диагностика.
Как устроен CapRover
В основе лежит Docker Swarm из одной ноды. Панель Captain доступна на порту 3000 при установке и по HTTPS после настройки домена. Внутренний nginx распределяет трафик, Certbot получает сертификаты Let’s Encrypt.
- Приложение — это Docker-сервис с именем вида
srv-captain--myapp. - Настройки хранятся в каталоге
/captain/data. - Одна панель управляет одним сервером; кластер из нескольких нод официально не поддерживается.
Это не Kubernetes: автомасштабирования и сложных политик здесь нет, зато порог входа низкий.
Подготовка сервера и установка
Нужен чистый Ubuntu 22.04 или 24.04, 2 ГБ RAM и 20 ГБ диска. A-запись captain.example.com и wildcard *.example.com направьте на IP сервера.
sudo apt update && sudo apt upgrade -y
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs git
sudo npm install -g caprover
Node.js из репозитория дистрибутива может быть старым, поэтому используется LTS-ветка NodeSource. Затем запустите мастер:
sudo caprover serversetup
sudo ufw allow 80,443,3000/tcp
sudo ufw allow 7946,4789/tcp
sudo ufw allow 7946,4789/udp
Мастер спросит IP, домен, почту и пароль. Он установит Docker, включит Swarm и поднимет контейнеры. Порты 7946 и 4789 нужны Swarm, 3000 — только для первичной настройки.
Проверьте DNS и ответ панели:
dig +short captain.example.com
curl -I https://captain.example.com
docker node ls
docker service ls
Первое приложение и captain-definition
Создайте приложение, укажите контейнерный порт и включите HTTPS. CapRover собирает из Dockerfile, разворачивает образ из реестра или отдаёт статику; для предсказуемости выбирайте Dockerfile и captain-definition.
{
"schemaVersion": 2,
"dockerfilePath": "./Dockerfile"
}
Для статики достаточно nginx и каталога со сборкой. В Node.js приложении задайте CMD ["node", "server.js"] и порт через переменную PORT: CapRover проксирует запросы на порт контейнера.
Деплой из терминала удобен в CI и на локальной машине:
npm install -g caprover
caprover deploy
caprover deploy -h https://captain.example.com -a myapp -b main
docker service logs -f srv-captain--myapp
Мастер попросит пароль или токен приложения. Токен даёт доступ только к одному приложению, но храните его в секретах CI, а не в репозитории.
Вторая схема — вебхук из Git: включите автодеплой и добавьте URL в GitHub, GitLab или Bitbucket. Сборка запустится после push в выбранную ветку; для приватных репозиториев нужен токен доступа.
Домены, HTTPS и переменные окружения
Приложение получает поддомен myapp.example.com; дополнительный домен добавляется в App Config. Не включайте HTTPS, пока DNS не указывает на сервер: Let’s Encrypt не выдаст сертификат.
Секреты задавайте через переменные окружения, а не в образе: после изменения CapRover перезапускает контейнер, а пароли и ключи не попадают в Git.
DATABASE_URL=postgres://app:secret@db:5432/app
NODE_ENV=production
PORT=3000
LOG_LEVEL=info
Не печатайте секреты в общий лог: выводите только имена переменных.
Базы данных и постоянные каталоги
В one-click apps есть PostgreSQL, MySQL, MariaDB, MongoDB и Redis. Они запускаются как отдельные приложения с внутренними именами. Строка подключения:
postgres://user:password@srv-captain--postgres:5432/dbname
psql "postgres://user:password@srv-captain--postgres:5432/dbname"
pg_dump -Fc "postgres://user:password@srv-captain--postgres:5432/dbname" > backup.dump
Без тома данные контейнера исчезнут при пересоздании. В App Config укажите Persistent Directories, например /var/lib/data, и CapRover создаст том. Для загрузок, кеша и SQLite это обязательно.
Для SQLite подойдёт постоянный каталог, но при нескольких репликах файл будет рассогласован; для командной работы выбирайте PostgreSQL или MySQL.
Резервное копирование и обновление
Бэкап делится на конфигурацию панели, тома приложений и дампы баз. Конфигурацию архивируйте вместе с /captain/data, лучше на остановленной панели. Имя тома приложения возьмите из вывода docker volume ls.
sudo tar czf /root/caprover-data-$(date +%F).tar.gz /captain/data
docker volume ls
docker run --rm -v VOLUME_NAME:/data -v /root:/backup alpine tar czf /backup/app-data.tar.gz -C /data .
docker service update --force --image caprover/caprover:latest captain-captain
Обновление перезапускает Captain. Перед ним проверьте журнал и читаемость бэкапа, после — панель, список приложений и логи сервиса.
Храните копии вне сервера и запускайте их по systemd timer или cron, проверяя размер файла и код возврата.
Диагностика типовых проблем
Если приложение не открывается, проверяйте цепочку: DNS, nginx, сервис, контейнер, приложение.
docker service ls
docker service ps srv-captain--myapp --no-trunc
docker service logs --tail 100 srv-captain--myapp
curl -I -H 'Host: myapp.example.com' http://127.0.0.1
503от nginx чаще означает, что контейнер не прошёл healthcheck или слушает не тот порт.- Ошибка сертификата — проверьте A-записи и доступность 80-го порта извне.
- Контейнер перезапускается — смотрите логи и лимиты памяти.
- Медленная сборка — ограничьте контекст через
.dockerignore.
Порты проверяйте через ss -tlnp, маршруты — через curl изнутри контейнера. Имена сервисов доступны только в overlay-сети Swarm.
Чек-лист перед продакшеном
- Домен и wildcard указывают на сервер, HTTPS включён для панели и приложений.
- Пароль администратора длинный, SSH закрыт ключами, fail2ban настроен.
- Порты 3000 и Docker API недоступны из интернета.
- Настроены постоянные каталоги и резервные копии с проверкой восстановления.
- Логи и метрики собираются, есть оповещение о падении сервиса.
- Обновления панели и образов выполняются по расписанию.
Итог
CapRover даёт веб-панель и привычный цикл деплоя без облачной привязки. Он хорошо подходит для небольшой команды, внутренних сервисов и pet-проектов, где не нужен кластер. Главное — заранее продумать домены, тома и бэкапы, а также не открывать панель и Docker API наружу. Если проект вырастет до нескольких нод и строгих SLA, миграция на Kubernetes или управляемую платформу станет естественным следующим шагом.