Зачем нужен CI/CD на VPS
CI/CD (Continuous Integration / Continuous Deployment) автоматизирует сборку, тестирование и развёртывание приложений. Вместо ручного деплоя по SSH каждый push в main-ветку запускает pipeline, который собирает Docker-образ, прогоняет тесты и обновляет приложение на VPS без простоя.
В 2026 году GitHub Actions остаётся самым популярным инструментом для CI/CD благодаря бесплатным 2000 минутам в месяц, возможности использовать self-hosted runners на своём VPS и интеграции с Docker.
Что даёт CI/CD разработчику
- Автоматический деплой — push в main = обновление на production за 2-5 минут без ручных действий.
- Раннее обнаружение ошибок — тесты прогоняются автоматически при каждом push, до попадания на сервер.
- Воспроизводимость сборки — Docker-образ гарантирует идентичное окружение на dev и production.
- Откат за секунды — при проблемах можно мгновенно вернуть предыдущий Docker-образ.
- Командная работа — каждый PR проходит проверки, merge в main автоматически деплоит.
Требования к VPS для CI/CD
Для комфортной работы CI/CD pipeline на VPS необходимы ресурсы для Docker-сборки и запуска self-hosted runner.
Минимальная конфигурация (1 проект)
- CPU: 2 vCPU
- RAM: 4 ГБ
- Диск: 50 ГБ NVMe SSD
- ОС: Ubuntu 22.04 или 24.04 LTS
- Docker + Docker Compose
- Статический IP-адрес
Для нескольких проектов
- CPU: 4 vCPU
- RAM: 8 ГБ
- Диск: 100 ГБ NVMe SSD
- Параллельные runners для разных репозиториев
Рекомендуемые провайдеры: Timeweb Cloud — от 390 руб./мес с NVMe и почасовой оплатой. RUVDS — от 500 руб./мес с 4 ГБ RAM. VDSina.ru — от 350 руб./мес с гибкой тарификацией.
Подготовка VPS: установка Docker и Docker Compose
Все команды актуальны для Ubuntu 22.04/24.04 по состоянию на 2026 год.
Установка Docker
sudo apt update && sudo apt upgrade -y
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
docker --versionУстановка Docker Compose
sudo apt install docker-compose-plugin -y
docker compose versionСоздание пользователя для деплоя
# Отдельный пользователь для безопасности
sudo useradd -m -s /bin/bash deployer
sudo usermod -aG docker deployer
# SSH-ключ для GitHub Actions
sudo su - deployer
ssh-keygen -t ed25519 -C "github-actions" -f ~/.ssh/github_deploy_key -N ""
cat ~/.ssh/github_deploy_key.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
cat ~/.ssh/github_deploy_key # Скопировать в GitHub SecretsНастройка GitHub Actions: SSH-деплой
Самый простой способ CI/CD — GitHub Actions деплоит на VPS через SSH. Не требует self-hosted runner.
Настройка секретов в GitHub
- Откройте репозиторий на GitHub
- Settings - Secrets and variables - Actions
- Добавьте секреты: VPS_HOST (IP сервера), VPS_USER (deployer), SSH_PRIVATE_KEY (приватный ключ), SSH_KNOWN_HOSTS (результат ssh-keyscan -H VPS_IP)
Workflow для Node.js приложения
# .github/workflows/deploy.yml
name: Deploy to VPS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
echo "${{ secrets.SSH_KNOWN_HOSTS }}" > ~/.ssh/known_hosts
- name: Deploy via SSH
run: |
ssh ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} << 'EOF'
cd /app/myproject
git pull origin main
docker compose build
docker compose up -d --remove-orphans
docker image prune -f
EOFПри каждом push в main: GitHub подключается к VPS по SSH, обновляет код через git pull, пересобирает Docker-образ и перезапускает контейнеры.
Self-hosted runner на VPS
Self-hosted runner — агент GitHub Actions, запущенный на вашем VPS. Билды выполняются локально, что быстрее и без лимитов на минуты.
Установка runner
# Создаём пользователя для runner
sudo useradd -m -s /bin/bash github-runner
sudo usermod -aG docker github-runner
su - github-runner
# Скачиваем runner (актуальная ссылка в Settings - Actions - Runners)
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.321.0.tar.gz -L \
https://github.com/actions/runner/releases/download/v2.321.0/actions-runner-linux-x64-2.321.0.tar.gz
tar xzf actions-runner-linux-x64-2.321.0.tar.gz
# Настройка (токен из GitHub Settings - Actions - Runners - New)
./config.sh --url https://github.com/YOUR/REPO --token YOUR_TOKEN
# Установка как системный сервис
sudo ./svc.sh install
sudo ./svc.sh start
sudo ./svc.sh statusWorkflow с self-hosted runner
# .github/workflows/deploy.yml
name: Build & Deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: self-hosted # Ваш runner на VPS
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker compose build
- name: Run tests
run: docker compose run --rm app npm test
- name: Deploy
run: |
docker compose down
docker compose up -d --remove-orphans
docker image prune -f
- name: Health check
run: |
sleep 10
curl -f http://localhost:3000/health || exit 1Self-hosted runner экономит время: нет задержки на запуск hosted runner и скачивание зависимостей. Docker-кеш хранится на VPS между запусками.
Docker Compose для production
Правильно настроенный docker-compose.yml — основа надёжного CI/CD. Включает healthcheck, restart policy, volumes и ограничения ресурсов.
Пример для Node.js
# docker-compose.yml
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
memory: 512M
cpus: "1.0"
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=${DB_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
pgdata:Пример для Python (FastAPI/Django)
# docker-compose.yml
services:
web:
build:
context: .
dockerfile: Dockerfile
command: gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
ports:
- "8000:8000"
environment:
- DATABASE_URL=${DATABASE_URL}
- SECRET_KEY=${SECRET_KEY}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
depends_on:
redis:
condition: service_healthy
redis:
image: redis:7-alpine
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10sZero-downtime деплой
Стандартный docker compose down && up вызывает простой на 5-30 секунд. Для production-сервисов это неприемлемо.
Rolling update с Docker Compose
# Обновление без остановки
docker compose pull
docker compose up -d --no-deps --build app
# Старый контейнер останавливается только после запуска новогоBlue-Green деплой
# Два профиля: blue и green
# docker-compose.yml
services:
app-blue:
build: .
ports: ["3001:3000"]
profiles: ["blue"]
app-green:
build: .
ports: ["3002:3000"]
profiles: ["green"]
# Nginx переключает upstream:
# upstream app { server localhost:3001; } # blue
# upstream app { server localhost:3002; } # greenBlue-Green подход: деплоите новую версию параллельно, проверяете health, переключаете Nginx upstream, останавливаете старую версию. Нулевой простой.
Безопасность CI/CD pipeline
CI/CD pipeline имеет доступ к серверу и секретам. Безопасность критически важна.
- Минимальные права — пользователь deployer без sudo, только Docker.
- SSH-ключи вместо паролей — Ed25519 ключи с ограничением по IP в authorized_keys.
- Ротация секретов — обновляйте SSH-ключи и токены каждые 90 дней.
- Ограничение self-hosted runner — не используйте на production-сервере для публичных репозиториев.
- Сканирование образов — docker scout cve перед деплоем.
- GITHUB_TOKEN scope — минимальные permissions в workflow.
# Ограничение SSH по IP в authorized_keys
from="203.0.113.0/24" ssh-ed25519 AAAA... github-actionsЗаключение
CI/CD на VPS с GitHub Actions и Docker — это инвестиция в скорость и надёжность разработки. SSH-деплой подходит для простых проектов, self-hosted runner — для команд с частыми деплоями. Docker Compose обеспечивает воспроизводимость, а blue-green деплой — нулевой простой.
Для запуска CI/CD достаточно VPS с 2 vCPU и 4 ГБ RAM от 400 руб./мес. Сравните тарифы провайдеров с Docker-поддержкой на EasyLinkLife.
Плюсы и минусы
Преимущества
- Готовые workflows для Node.js и Python
- SSH-деплой и self-hosted runner
- Docker Compose для production с healthchecks
- Zero-downtime: rolling update и blue-green
- Безопасность pipeline с конкретными мерами
Недостатки
- Не покрывает GitLab CI и Bitbucket Pipelines подробно
- Нет примеров для Go и Java
- Blue-green требует дополнительной настройки Nginx
Частые вопросы
Какой VPS нужен для CI/CD с GitHub Actions?
Минимум: 2 vCPU, 4 ГБ RAM, 50 ГБ NVMe SSD с Docker. Для нескольких проектов: 4 vCPU, 8 ГБ RAM. Стоимость от 400 руб./мес у российских провайдеров.
Self-hosted runner или SSH-деплой: что лучше?
SSH-деплой проще в настройке и подходит для 1-2 проектов. Self-hosted runner быстрее (локальный Docker-кеш), без лимитов на минуты и подходит для команд.
Безопасно ли использовать self-hosted runner?
Для приватных репозиториев — да. Для публичных — нет: любой PR может выполнить код на вашем сервере. Используйте отдельного пользователя без sudo.
Как настроить zero-downtime деплой на VPS?
Используйте docker compose up -d --no-deps --build для rolling update. Для полного zero-downtime — blue-green деплой с переключением Nginx upstream.
Сколько стоит GitHub Actions?
2000 минут бесплатно в месяц для hosted runners. Self-hosted runner — полностью бесплатно, платите только за VPS.
Можно ли использовать GitLab CI вместо GitHub Actions?
Да, GitLab CI работает аналогично с GitLab Runner. Настройка .gitlab-ci.yml вместо .github/workflows/. Принципы Docker-деплоя на VPS идентичны.
VPS для CI/CD с Docker
Выбрать VPS для деплояНекоторые ссылки в этой статье являются партнёрскими. Мы можем получить комиссию при переходе и покупке. На стоимость для вас это не влияет. Подробнее