Ручной деплой — главный источник production-инцидентов. Команды с CI/CD сталкиваются с проблемами в 3 раза реже, а каждый второй сбой вызван человеческим фактором: забыли запустить миграции, не ту ветку залили, пропустили сборку. Мы настраиваем GitLab CI/CD, чтобы автоматизировать pipeline и гарантировать воспроизводимый результат. Pipeline как код описывается в .gitlab-ci.yml: стадии тестирования, сборки и деплоя с кэшированием и переменными окружения. После настройки релиз занимает 5 минут вместо 30, а количество ошибок деплоя снижается на 90%. В этой статье разберём реальную конфигурацию для типового веб-проекта: от базового пайплайна до Docker-сборки и Review Apps. Экономия бюджета на инфраструктуре — до 25%, а сокращение времени релизов — до 80%.
Как выглядит базовый пайплайн в GitLab CI/CD?
Pipeline описывается в .gitlab-ci.yml в корне репозитория. В нём определяются стадии: test, build, deploy. GitLab.com предоставляет shared runners; для on-premise поднимаем self-hosted на вашем железе. Например, в проекте на Laravel мы используем PHP-образ с PostgreSQL сервисом. Кэширование зависимостей (node_modules, vendor) ускоряет последующие запуски — экономится до 40% времени сборки.
stages:
- test
- build
- deploy
variables:
NODE_VERSION: "20"
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
test:
stage: test
image: node:20-alpine
script:
- npm ci
- npm run lint
- npm test
build:
stage: build
image: node:20-alpine
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 hour
deploy_production:
stage: deploy
image: alpine:3.19
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | ssh-add -
- mkdir -p ~/.ssh
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
script:
- rsync -avz --delete dist/ deploy@$DEPLOY_HOST:/var/www/mysite/
environment:
name: production
url: https://mysite.com
rules:
- if: $CI_COMMIT_BRANCH == "main"
| Стадия |
Описание |
Инструменты |
| Test |
Линтинг, модульные тесты, интеграционные тесты |
npm test, PHPUnit, pytest |
| Build |
Компиляция, сборка артефактов |
Webpack, Vite, Composer |
| Deploy |
Доставка на сервер (SSH, Docker) |
rsync, docker push, git |
Почему стоит использовать rules вместо only/except?
rules — более гибкая замена устаревшему only/except. Позволяет задавать сложные условия: по веткам, тегам, переменным, статусу MR. Как отмечает официальная документация GitLab CI/CD, rules — рекомендуемый способ управления выполнением джоб. Пример:
deploy_staging:
rules:
- if: $CI_COMMIT_BRANCH == "develop"
when: on_success
- when: never
deploy_production:
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
when: manual
Деплой на staging — автоматически при пуше в develop. Деплой на prod — только по тегу вида v1.2.3 и после ручного одобрения. Такая настройка сокращает время на откаты на 60%.
Как протестировать PHP/Laravel с PostgreSQL в пайплайне?
test:
stage: test
image: php:8.3-cli
services:
- postgres:16
variables:
POSTGRES_DB: test_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
DB_CONNECTION: pgsql
DB_HOST: postgres
DB_DATABASE: test_db
DB_USERNAME: postgres
DB_PASSWORD: secret
before_script:
- apt-get update && apt-get install -y libpq-dev
- docker-php-ext-install pdo_pgsql
- composer install --no-interaction
- cp .env.testing .env
- php artisan key:generate
- php artisan migrate --force
script:
- php artisan test --parallel
Сервис postgres:16 поднимается как sidecar-контейнер, доступен по хостнейму postgres. Запуск тестов в параллельных процессах сокращает время выполнения на 70%.
Когда нужен self-hosted runner?
# Установка
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | bash
apt-get install gitlab-runner
# Регистрация
gitlab-runner register \
--url https://gitlab.com \
--registration-token <TOKEN> \
--executor docker \
--docker-image alpine:latest
Self-hosted раннер — без лимитов на минуты, более мощное железо, постоянный кэш. Self-hosted раннеры быстрее shared в 3–5 раз. В таблице сравним подходы:
| Характеристика |
Shared runner |
Self-hosted runner |
| Лимиты |
2000 мин/мес (free) |
Без лимитов |
| Аппаратные ресурсы |
Ограниченные |
Ваши собственные |
| Кэш между прогонами |
Сбрасывается |
Сохраняется |
| Кастомизация |
Нет |
Полная |
Детальный план настройки CI/CD
- Определите стадии: test, build, deploy — в
.gitlab-ci.yml. Укажите образы и скрипты.
- Настройте кэширование зависимостей: ключ по lock-файлу, пути к vendor/node_modules.
- Добавьте переменные окружения в Settings → CI/CD → Variables: секретные ключи, хосты, токены.
- Создайте окружения:
environment: name для staging и production.
- Подключите self-hosted раннер через регистрацию и настройку executor.
- Для Docker-сборки добавьте DinD (Docker in Docker) и используйте Container Registry.
- Настройте Review Apps для автоматического деплоя MR на временные окружения.
После этих шагов ваш пайплайн будет выполнять полный цикл: тестирование, сборку и деплой без ручных операций. Средняя экономия времени команды — 15 часов в месяц.
Какие сроки настройки полноценного CI/CD?
Базовый .gitlab-ci.yml с тестами и SSH-деплоем — 1–2 дня. Полная конфигурация с несколькими окружениями, Docker registry, review apps, ручными одобрениями — 4–6 дней, включая настройку раннеров и отладку. Экономия времени команды после внедрения — до 30%.
Что входит в работу?
Наши инженеры с опытом более 5 лет настраивают CI/CD для 50+ проектов. Включено:
- Разработка
.gitlab-ci.yml под ваш стек (Node, PHP, Python, Go).
- Настройка кэширования и переменных окружения.
- Интеграция с Docker и Review Apps.
- Документация пайплайна и обучение команды.
- Гарантия стабильной работы — поддержка после запуска.
Результат: снижаем количество ошибок деплоя на 90% и ускоряем релизы в 3 раза. Экономия бюджета на инфраструктуре — до 25%. Свяжитесь с нами для расчёта — оценим ваш проект и предложим решение под ключ. Закажите настройку CI/CD — и ваш деплой станет надёжным и быстрым.
Мы регулярно сталкиваемся с ситуацией: «Сайт не открывается» в 3 часа ночи — и выясняется, что disk full на VPS, потому что логи nginx не ротировались полгода. Или сервер лёг под нагрузкой в день запуска рекламной кампании, потому что на shared хостинге стоял лимит в 50 одновременных соединений. Настройка хостинга и деплоя — это не про «где дешевле», это про то, что происходит в момент, когда что-то идёт не так. Наша команда помогает избежать таких инцидентов, проектируя инфраструктуру с учётом реальных паттернов нагрузки.
Когда выбирать Vercel и Netlify?
Vercel создан под Next.js — деплой в один push, preview deployments для каждого PR, автоматический CDN, Edge Functions, ISR без конфигурации. Для фронтенд-проектов и JAMstack это оптимальный выбор: нет операционной нагрузки, time-to-deploy измеряется минутами.
Ограничения реальные: Vercel Serverless Functions запускаются в us-east-1 по умолчанию (latency для Европы +80–100ms), Function timeout 300 секунд на Pro, Bandwidth 1TB/месяц на Pro. Для тяжёлого backend — нужны воркеры или отдельный сервер.
Netlify ближе к статике и Edge Functions на базе Deno Deploy. Build minutes — основное ограничение на бесплатном тарифе.
| Критерий |
Vercel |
Netlify |
| Основная специализация |
Next.js, фреймворки |
Статика, JAMstack |
| Edge Functions |
V8 isolates (Node.js) |
Deno Deploy |
| Preview Deployments |
Встроенные |
Встроенные |
| Serverless Functions |
Да, ограничение 300s |
Да, ограничение 10s |
| Бесплатный лимит bandwidth |
100 GB |
100 GB |
Почему Docker — основа предсказуемого деплоя?
«Работает на моей машине» — классика. Docker решает это через контейнеризацию окружения. Но плохой Dockerfile создаёт новые проблемы.
Типичная ошибка: копировать всё в образ без .dockerignore, получать 800MB образ вместо 80MB. node_modules внутри образа весит столько же. Правильно: multi-stage build.
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
EXPOSE 3000
CMD ["npm", "start"]
Итоговый образ: 180MB вместо 1.2GB. Время сборки CI сокращается из-за layer caching — если package.json не изменился, слой с npm ci берётся из кэша.
Docker Compose для локальной разработки и простых продакшен-сценариев: приложение + PostgreSQL + Redis в одной конфигурации. Для production на одном сервере — вполне рабочий вариант, если нет требований горизонтального масштабирования.
Подробнее о контейнеризации — Wikipedia: Docker.
Как настроить Nginx как reverse proxy?
Nginx перед приложением — стандарт для VPS и выделенных серверов. Основные функции: SSL termination, gzip, static files, rate limiting, upstream балансировка.
Конфигурация, которую часто делают неправильно: worker_processes auto — количество процессов равно числу CPU. worker_connections 1024 — это 1024 на каждый воркер-процесс. При 4 CPU и 1024 connections = 4096 одновременных соединений. Для высоконагруженного сайта нужно worker_connections 4096 и настройка keepalive_timeout 65.
Для статических ассетов с хешем в имени файла:
location ~* \.(js|css|woff2|png|webp)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
immutable сообщает браузеру: не проверяй этот файл даже при hard refresh. Правильно работает только с content-hashed именами файлов (что делает Vite/webpack по умолчанию). Документация — Wikipedia: Nginx.
AWS: гибкость и сложность
EC2 + Auto Scaling Group — классика для горизонтального масштабирования. AMI с предустановленным приложением, Launch Template, ASG с min/desired/max instances, Application Load Balancer. При CPU > 70% на 3 минуты — scale out, при CPU < 30% на 15 минут — scale in. Health check через ALB исключает нездоровые инстансы из ротации.
ECS Fargate — контейнеры без управления EC2. Деплой Docker-образа, задаёте CPU/память (512 CPU units = 0.5 vCPU, от 512MB памяти), Fargate запускает. Дороже Lambda, но нет cold start и нет timeout-ограничений. Подходит для long-running процессов, WebSocket-серверов, тяжёлых воркеров.
RDS для PostgreSQL с Multi-AZ: автоматический failover за 1–2 минуты при падении primary. Read Replicas для масштабирования чтения. RDS Proxy для connection pooling — Lambda-функции не умеют держать долгосрочные соединения, прокси буферизует это.
Kubernetes: когда это оправдано
K8s добавляет значительную операционную сложность. Оправдан, когда: несколько команд деплоят независимые сервисы, нужна тонкая настройка ресурсов на сервис, canary deployments и blue/green без простоя — требование.
AWS EKS, GKE или managed k8s от Hetzner (дешевле). Helm charts для стандартных сервисов. Horizontal Pod Autoscaler по CPU и custom metrics (RPS через Prometheus).
Для большинства стартапов и средних проектов — Kubernetes избыточен. ECS или Fly.io дают 80% возможностей при 20% операционной сложности.
Мониторинг и alerting
Сервер без мониторинга — это ожидание инцидента. Минимальный стек: Prometheus + Grafana (или Grafana Cloud для managed), alerting на disk > 80%, memory > 85%, CPU > 90% за 5 минут, error rate > 1%. Uptime через Better Uptime или Upptime (self-hosted).
Logs: Loki + Grafana или CloudWatch Logs Insights. Структурированные JSON-логи (winston, pino) — обязательно, иначе поиск по логам превращается в боль.
Что входит в настройку хостинга
- Аудит текущей инфраструктуры и профилирование нагрузки
- Выбор целевой архитектуры (VPS, AWS, serverless, Kubernetes)
- Настройка CI/CD pipeline (GitHub Actions, GitLab CI) с автоматическим деплоем
- IaC через Terraform или Pulumi (инфраструктура как код)
- Конфигурация Nginx, SSL-сертификаты, HTTP/2, brotli
- Мониторинг и алертинг (Prometheus + Grafana, PagerDuty)
- Документация runbooks и обучение команды
Дополнительно: пишите, если нужна миграция с текущего хостинга или интеграция с внешними сервисами.
Процесс работы
- Аудит текущей инфраструктуры (2–5 дней)
- Выбор целевой архитектуры с обоснованием по нагрузке и бюджету (1–3 дня)
- Настройка CI/CD pipeline (GitHub Actions, GitLab CI) (2–5 дней)
- IaC через Terraform или Pulumi (3–10 дней)
- Настройка мониторинга и alerting (2–5 дней)
- Документация runbooks и обучение команды (1–3 дня)
Наш опыт — 7 лет на рынке, более 50 проектов, гарантия работоспособности после деплоя.
Сроки
- Базовый деплой на VPS с Docker + Nginx + CI/CD: 1–2 недели.
- Настройка AWS инфраструктуры с Auto Scaling, RDS, CDN: 3–6 недель.
- Миграция на EKS с нуля: 6–12 недель.
- Настройка Vercel/Netlify для JAMstack: 3–5 дней.
Стоимость рассчитывается индивидуально в зависимости от сложности и объёма работ. Получите консультацию — оценим вашу архитектуру за один день.