Автоматическое развёртывание с GitHub Actions: настройка CI/CD Pipeline
Создание CI/CD-пайплайнов с GitHub Actions: сборка и публикация Docker, развёртывание на сервере по SSH, автоматизация тестов, управление секретами и оптимизация рабочих процессов.
Содержание
Автоматическое развёртывание с GitHub Actions: настройка CI/CD Pipeline
GitHub Actions — мощная CI/CD-платформа, которая автоматически тестирует, собирает и развёртывает изменения кода на сервере. В этом руководстве мы создадим готовый к production пайплайн с нуля.
Что такое GitHub Actions?
GitHub Actions — платформа автоматизации, интегрированная в репозитории GitHub:
- Реагирует на события: push, PR, расписание
- Запускает параллельные и последовательные рабочие процессы
- 2 000 минут/месяц бесплатно (неограниченно для публичных репозиториев)
- Расширяется тысячами готовых actions
Файлы рабочих процессов GitHub Actions хранятся в формате YAML в директории .github/workflows/.
Базовая структура рабочего процесса
# .github/workflows/deploy.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Настройка Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Установка зависимостей
run: npm ci
- name: Запуск тестов
run: npm test
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Развернуть
run: echo "Шаги развёртывания здесь"
Структура on / jobs / steps
Триггеры (on)
on:
# Push в ветку
push:
branches: [main, develop]
paths:
- 'src/**'
- 'package.json'
# Pull request
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
# Запуск по расписанию (cron)
schedule:
- cron: '0 2 * * *' # Каждую ночь в 02:00
# Ручной запуск
workflow_dispatch:
inputs:
environment:
description: 'Среда развёртывания'
required: true
default: 'staging'
type: choice
options: [staging, production]
# При завершении другого рабочего процесса
workflow_run:
workflows: ["Build"]
types: [completed]
Конфигурация задания
jobs:
build:
runs-on: ubuntu-latest
env:
NODE_ENV: test
timeout-minutes: 30
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
Сборка и публикация Docker
Публикация в Docker Hub
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Метаданные Docker
id: meta
uses: docker/metadata-action@v5
with:
images: username/myapp
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=sha,prefix=sha-
- name: Настройка Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Вход в Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Сборка и публикация
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
GitHub Container Registry (GHCR)
- name: Вход в GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Сборка и публикация (GHCR)
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:latest
Развёртывание на сервере по SSH
Использование appleboy/ssh-action
deploy:
needs: docker
runs-on: ubuntu-latest
environment: production
steps:
- name: Развёртывание по SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SERVER_PORT }}
script: |
cd /root/myapp
git pull origin main
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
echo "Развёртывание завершено: $(date)"
Развёртывание с Docker Compose
- name: Развёртывание Docker Compose
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
# Получить новый образ
docker pull ghcr.io/${{ github.repository }}:latest
# Развёртывание без простоя
docker compose -f /root/app/docker-compose.yml up -d \
--no-deps \
--build \
--remove-orphans
# Очистить старые образы
docker image prune -af --filter "until=24h"
# Проверка работоспособности
sleep 10
curl -f http://localhost:3000/health || exit 1
Управление секретами
GitHub Secrets надёжно хранит конфиденциальную информацию:
steps:
- name: Конфигурация приложения
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
API_KEY: ${{ secrets.API_KEY }}
run: |
echo "Конфигурация загружена"
# Секреты никогда не выводятся в логи, автоматически маскируются
Необходимые секреты:
SERVER_HOST: IP-адрес сервераSERVER_USER: имя пользователя SSHSSH_PRIVATE_KEY: приватный ключ SSHDOCKERHUB_USERNAME: имя пользователя Docker HubDOCKERHUB_TOKEN: токен доступа Docker Hub
Использование кэша
- name: Кэширование зависимостей Node.js
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: npm ci (с кэшем)
run: npm ci
# Кэш слоёв Docker
- name: Сборка и публикация
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
Matrix Builds
jobs:
test:
strategy:
fail-fast: false
matrix:
node: [18, 20]
os: [ubuntu-latest, macos-latest]
include:
- node: 20
os: ubuntu-latest
coverage: true
exclude:
- node: 18
os: macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
- name: Отчёт о покрытии
if: matrix.coverage
run: npm run coverage
Правила защиты окружений
jobs:
deploy-production:
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- name: Развёртывание в production
run: echo "Развёртывание в production"
В GitHub в разделе Settings > Environments > production:
- Required reviewers (требуется одобрение)
- Wait timer (время ожидания)
- Deployment branches (только main)
Полный пример CI/CD Pipeline
name: Full CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test -- --coverage
- name: Загрузить покрытие
uses: codecov/codecov-action@v4
build:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: docker/build-push-action@v5
with:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment:
name: production
url: https://example.com
steps:
- uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
docker compose -f /root/app/docker-compose.yml up -d
docker image prune -f
Заключение
Настроив полностью автоматизированный CI/CD-пайплайн с GitHub Actions, вы сможете повысить качество кода, сократить ошибки при развёртывании и ускорить процесс разработки. Управление секретами, оптимизация кэша и правила защиты окружений обеспечат вам пайплайн production-уровня.
Связанные статьи
Руководство по Docker Compose: Управление многоконтейнерными приложениями
Определение и управление многоконтейнерными приложениями с Docker Compose: зависимости сервисов, переменные окружения, проверки работоспособности, масштабирование и развёртывание в production. Полное руководство.
Автоматизация серверов с Ansible: Infrastructure as Code
Установка Ansible, файл инвентаря, написание playbook, структура ролей, переменные, зашифрованный vault, ad-hoc команды и автоматизация конфигурации серверов. Пошаговое руководство.
Настройка веб-сервера Caddy: автоматический HTTPS и обратный прокси
Установка веб-сервера Caddy, настройка Caddyfile, автоматический SSL от Let's Encrypt, обратный прокси, хостинг статических сайтов, интеграция PHP-FPM и настройки производительности.