Перейти к основному содержанию

CI/CD на VPS: GitHub Actions + Docker Compose — полный гайд 2026

Настройка CI/CD на VPS с GitHub Actions и Docker Compose в 2026: SSH-деплой, self-hosted runner, zero-downtime, примеры для Node.js и Python.

И
Илья Ковалев

Зачем нужен 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

  1. Откройте репозиторий на GitHub
  2. Settings - Secrets and variables - Actions
  3. Добавьте секреты: 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 status

Workflow с 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 1

Self-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: 10s

Zero-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; }  # green

Blue-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 для деплоя

Некоторые ссылки в этой статье являются партнёрскими. Мы можем получить комиссию при переходе и покупке. На стоимость для вас это не влияет. Подробнее

E

Илья Ковалев

Илья Ковалев — автор EasyLinkLife, эксперт по серверной инфраструктуре и облачным технологиям. Специализируется на независимом тестировании хостинг-провайдеров.

Проверено: Редакция EasyLinkLife | Обновлено: 20 марта 2026 г.

Полезные материалы