Created by AIImproved by people
Riqli · living documents · updated continuously
Where AI knowledge meets human practice.
Share with friends

Введение
Аннотация. Данный курс посвящен внедрению современного подхода к разработке и поставке программного обеспечения, основанному на методологии непрерывной интеграции и непрерывной доставки (CI/CD) в связке с контейнеризацией. Основная проблема, которую решает курс — это хаос ручного деплоя, высокий риск человеческих ошибок и различия в средах выполнения, из-за которых приложение «работает на моей машине», но падает на сервере. Мы предлагаем системное решение: автоматизированный пайплайн на базе GitHub Actions и изолированные окружения, построенные на Docker. Этот подход особенно актуален для full-stack разработки, где необходимо быстро и безопасно доставлять изменения пользователям, обеспечивая при этом стабильность и масштабируемость продукта.
Цель курса. После прохождения курса вы сможете самостоятельно проектировать, настраивать и сопровождать CI/CD пайплайн для полного цикла разработки full-stack приложений, используя GitHub Actions для автоматизации и Docker для создания воспроизводимых окружений, обеспечивая надежное развертывание в облачные среды или на собственные серверы.
Результаты обучения.
- Знать: архитектуру и компоненты CI/CD; принципы работы Docker (образы, контейнеры, слои, реестры); синтаксис и возможности GitHub Actions (воркфлоу, джобы, степы, экшены); стратегии безопасного хранения секретов и управления версиями.
- Уметь: писать Dockerfile для создания легковесных и безопасных образов; создавать YAML-манифесты для автоматизации сборки, тестирования и деплоя; публиковать образы в Docker Hub или GitHub Container Registry (GHCR); автоматически обновлять приложения на удаленных серверах по SSH.
- Владеть: навыками отладки пайплайнов; принципами zero-downtime деплоя (обновление без остановки); техниками оптимизации времени сборки (кэширование, multistage build); подходами к мониторингу и rollback-стратегиям.
Для кого этот курс.
Курс создан для full-stack разработчиков, DevOps-инженеров и системных администраторов, которые хотят перейти от рутины ручного деплоя к современным автоматизированным практикам. Он будет полезен как начинающим специалистам, желающим освоить востребованный стек DevOps, так и опытным разработчикам, стремящимся систематизировать знания о контейнеризации и CI/CD, а также внедрить лучшие практики в свои проекты.
Курс не рассчитан на абсолютных новичков в программировании — предполагается базовое знакомство с Git, командной строкой Linux и понимание принципов веб-разработки.
Модуль 1. Основы CI/CD и значение автоматизации
Что такое CI/CD и почему это стандарт индустрии. CI/CD — это фундаментальная практика DevOps, объединяющая непрерывную интеграцию (CI) и непрерывную доставку/развертывание (CD). Непрерывная интеграция подразумевает частые слияния кода в общую ветку (например, main), за которыми следует автоматическая сборка и прогон тестов. Это позволяет обнаружить конфликты и ошибки на ранних стадиях. Непрерывная доставка (Continuous Delivery) гарантирует, что код после прохождения CI всегда готов к релизу, а Continuous Deployment автоматизирует процесс выкладки в продакшн-окружение. Внедрение CI/CD сокращает время выхода фич (Time-to-Market), повышает качество кода за счет автоматизированного тестирования и минимизирует человеческий фактор. По данным отраслевых отчетов, более 80% компаний используют контейнеризацию и пайплайны для ускорения разработки.
GitHub Actions как платформа для CI/CD. GitHub Actions — это встроенная платформа для автоматизации процессов разработки, доступная в любом репозитории GitHub. В отличие от внешних инструментов (Jenkins, GitLab CI), она нативно интегрируется с хостингом кода. Основной единицей является воркфлоу (workflow) — автоматический процесс, описываемый в YAML-файле и хранящийся в директории .github/workflows. Воркфлоу запускается по событиям (push, pull_request, schedule). Он состоит из джобов (jobs), которые выполняются параллельно или последовательно. Каждая джоба — это набор степов (steps), выполняющих либо shell-команды, либо сторонние готовые экшены (actions) из маркетплейса. GitHub Actions предоставляет раннеры (виртуальные машины) с Ubuntu, Windows или macOS, что делает его универсальным решением для сборки, тестирования и деплоя любых приложений.
Жизненный цикл разработки и место CI/CD. В жизненном цикле ПО пайплайн занимает центральное место между написанием кода и его эксплуатацией. Стандартный цикл выглядит так: разработчик создает фичу, делает коммит и пуш в репозиторий. Система контроля версий (Git) отправляет сигнал в GitHub Actions, который запускает процесс CI: линтер проверяет стиль кода, юнит-тесты и интеграционные тесты проверяют логику приложения. После успешного прохождения тестов запускается этап сборки — создается артефакт. На этапе CD этот артефакт упаковывается в Docker-образ и отправляется в реестр. Затем пайплайн подключается к серверу (через SSH или API) и обновляет работающий контейнер. Внедрение CI/CD делает процесс предсказуемым: каждый коммит в main проходит одинаковый путь проверок и деплоя.
Модуль 2. Погружение в Docker: контейнеризация приложений
Контейнеризация и ее отличие от виртуализации. Docker — это платформа для контейнеризации, которая решает проблему «работает на моей машине» за счет изоляции приложения на уровне операционной системы. В отличие от виртуальных машин (ВМ), которые эмулируют аппаратное обеспечение и загружают полноценную ОС, контейнеры используют ядро хостовой системы. Это делает их невероятно легкими — они весят мегабайты, а не гигабайты, и запускаются за секунды. Контейнеры используют механизмы ядра Linux: пространства имен (namespaces) обеспечивают изоляцию процессов, сети и файловой системы, а контрольные группы (cgroups) ограничивают потребление ресурсов (CPU, RAM). Это позволяет запускать десятки контейнеров на одном сервере, что значительно экономит инфраструктурные затраты и упрощает масштабирование.
Архитектура Docker: демон, клиент и реестры. Платформа Docker построена по архитектуре клиент-сервер. Центральным элементом является Docker Daemon (демон) — фоновый процесс, который управляет объектами: контейнерами, образами, сетями и томами. Пользователь взаимодействует с демоном через Docker Client (команда docker в терминале), который отправляет API-запросы. Для хранения и распространения готовых сборок существуют реестры образов (Registry). Публичным реестром по умолчанию является Docker Hub, где хранятся миллионы готовых образов (например, nginx, node, postgres). Для корпоративной разработки и безопасности используются приватные реестры, такие как GitHub Container Registry (GHCR), Amazon ECR или Azure Container Registry. Взаимодействие между клиентом и реестром происходит через команды docker pull (скачать) и docker push (загрузить).
Образы и слои (UnionFS). Ключевое понятие в Docker — это образ (Image). Образ — это неизменяемый (read-only) шаблон, содержащий приложение и все его зависимости для запуска. Образ строится из набора слоев, каждый из которых соответствует команде в Dockerfile. Такая слоистая архитектура (Union File System) позволяет эффективно кэшировать изменения: если слои не изменились, Docker использует их из кэша, что ускоряет пересборку. Каждый слой содержит дельту изменений от предыдущего состояния. При запуске контейнера поверх неизменяемых слоев образа создается тонкий слой записи (container layer). Все изменения, происходящие внутри работающего контейнера, записываются в этот слой. Однако при удалении контейнера этот слой уничтожается вместе с данными, что делает контейнеры эфемерными (stateless). Поэтому для постоянного хранения данных используются тома (volumes).
Написание Dockerfile и best practices. Dockerfile — это текстовый файл с инструкциями для сборки образа. Он всегда начинается с директивы FROM, указывающей базовый образ (например, FROM node:18-alpine). Далее идут команды: WORKDIR (задает рабочую папку), COPY (копирует файлы), RUN (выполняет команды во время сборки, например, установку зависимостей), EXPOSE (указывает порт) и CMD или ENTRYPOINT (команда запуска приложения). Критически важные практики: 1) Использование multistage builds для уменьшения размера финального образа (в продакшн попадает только собранный код, без компиляторов). 2) Копирование зависимостей отдельно от кода (COPY package*.json . перед COPY . .), чтобы использовать кэш слоев. 3) Запуск приложения от непривилегированного пользователя (USER) для безопасности.
Базовое управление контейнерами и томами. Управление жизненным циклом контейнеров осуществляется через CLI. Команда docker run -d --name my-app -p 8080:80 nginx запускает контейнер в фоне (-d), пробрасывая порт 80 контейнера на порт 8080 хоста. Для работы с состоянием используются тома (Volumes) и bind mounts. Том — это управляемая Docker сущность для хранения данных, независимая от контейнера. Bind mount монтирует конкретную папку на хосте внутрь контейнера — это удобно для разработки, так как изменения в коде сразу отражаются без пересборки. Для работы со сложными приложениями, состоящими из нескольких сервисов (например, frontend + backend + база данных), используется Docker Compose. Это инструмент, который позволяет описывать и запускать многоконтейнерные приложения с помощью YAML-файла, одной командой docker compose up -d поднимая всю инфраструктуру.
Модуль 3. Интеграция Docker и GitHub Actions
Настройка секретов и переменных окружения в GitHub. Безопасность — критический аспект CI/CD. Любой пайплайн должен иметь доступ к конфиденциальным данным: паролям реестров, SSH-ключам, API-ключам. Для этого в GitHub Actions используется два механизма: Secrets (зашифрованные секреты, недоступные для просмотра после создания, например, DOCKERHUB_TOKEN) и Variables (открытые переменные, например, имя пользователя DOCKER_USERNAME). Настройки хранятся в репозитории: Settings → Secrets and variables → Actions. В воркфлоу доступ к ним осуществляется через синтаксис {{ secrets.SECRET_NAME }} и {{ vars.VAR_NAME }}. Для безопасного деплоя на сервер через SSH создается пара ключей ed25519, приватный ключ сохраняется как секрет, а публичный добавляется в файл authorized_keys на сервере.
Action по сборке образов: docker/build-push-action. Официальный GitHub Action для работы с Docker — docker/build-push-action — является стандартом индустрии. Он интегрируется с Buildx, позволяя создавать образы для нескольких архитектур (например, linux/amd64 и linux/arm64). Ключевые параметры: context (путь к проекту), push (флаг отправки в реестр), tags (теги образа, например, latest или хэш коммита). Важнейшей фичей является кэширование слоев (cache-from, cache-to), которое позволяет сократить время сборки с нескольких минут до секунд, используя кэш GitHub Actions. Использование этого экшена вместо ручного вызова docker build внутри степа дает гибкость и поддержку лучших практик мультиплатформенной сборки.
Пайплайн тестирования и сборки. Эффективный пайплайн должен проверять качество кода до развертывания. Типовая структура включает несколько джобов. Первая джоба — Линтинг и Тестирование (запуск npm test или pytest). Вторая джоба — Сборка образа, которая стартует только в случае успеха тестов (needs: test). На этом этапе используется docker/build-push-action с флагом push: false, чтобы проверить, компилируется ли образ. Это экономит ресурсы, предотвращая загрузку «сломанных» образов в реестр. Часто используется техника именования образа по хэшу коммита (${{ github.sha }}), чтобы каждый коммит имел уникальную сборку. После успешной верификации джоба с деплоем (обычно вручную или автоматом) тянет этот конкретный образ и разворачивает его на сервере.
Автоматический деплой на VPS через SSH. Самый распространенный способ доставки кода в продакшн — использование SSH для подключения к серверу и обновления контейнеров. Это реализуется с помощью экшена appleboy/ssh-action. В степе передаются переменные сервера (host, username, key из секретов). Скрипт внутри script выполняет последовательность действий: логинится в реестр (docker login), переходит в папку с проектом, выполняет docker compose pull (скачивает новую версию образа) и docker compose up -d (перезапускает сервисы с новой версией без остановки, если настроено корректно). Для гарантии стабильности в пайплайн добавляется health check — проверка эндпоинта /health через wget или curl сразу после поднятия контейнера.
Модуль 4. Продвинутые техники и лучшие практики
Стратегия Zero-Downtime Deploy (обновление без остановки). При деплое критично не ронять приложение для пользователей. Docker Compose поддерживает zero-downtime обновления при использовании тэга latest (или свежего тега) с командой docker compose up -d, которая автоматически пересоздает контейнеры с новым образом, если изменилась конфигурация или образ, при этом старые контейнеры продолжают работать до момента успешного старта новых. Для full-stack приложений с базами данных важно соблюдать порядок: сначала обновлять сервисы без изменений схемы данных, затем выполнять миграции. Более надежный подход — стратегия Blue/Green или Canary (канареечные релизы), но на уровне VPS их сложнее реализовать вручную; там чаще используют Rolling Update через Compose или оркестраторы типа Kubernetes.
Rollback: как откатить неудачный релиз. Автоматический откат — признак зрелого пайплайна. В GitHub Actions логика проста: если после деплоя health check вернул ошибку (например, HTTP 500), пайплайн помечается как failed, и для восстановления нужно вручную или автоматически переключиться на предыдущий рабочий образ. Простейший способ — хранить теги версий (например, v1.0.1) и использовать docker compose up -d --no-build с указанием конкретного тега. В экшене appleboy/ssh-action можно реализовать проверку: если новый образ не прошел хелс-чек, выполняется docker compose restart или docker compose up -d с предыдущей версией. Для управления историями образов используются политики тегирования на основе хэша коммита (git rev-parse --short HEAD) или даты, что позволяет легко вернуться к любой предыдущей сборке.
Оптимизация времени сборки и кэширование. Скорость пайплайна напрямую влияет на скорость доставки фич. Ключевой метод — кэширование слоев Docker. В GitHub Actions это реализуется через docker/build-push-action с параметрами cache-from: type=gha и cache-to: type=gha,mode=max. Это сохраняет кэш в облачное хранилище GitHub (скорость доступа высока). Также важно правильно составлять Dockerfile: сначала копировать файлы зависимостей (package-lock.json), устанавливать их (npm ci), и только потом копировать исходный код. Это гарантирует, что при изменении кода (что происходит часто) слой с зависимостями не пересобирается. Для больших монорепозиториев рекомендуется использовать Docker BuildKit с параллельной сборкой этапов.
Безопасность контейнеров и сканирование уязвимостей. Безопасность контейнера начинается с базового образа: предпочтительнее использовать alpine или официальные slim версии для минимизации поверхности атаки. В пайплайн можно встроить этап сканирования уязвимостей. Отличный инструмент с открытым исходным кодом — Trivy. Действие (action) для GitHub: aquasecurity/trivy-action. Оно сканирует файловую систему или сам образ на наличие известных CVE (Common Vulnerabilities and Exposures) в зависимостях. Рекомендуется настраивать порог серьезности (критические/высокие уязвимости должны фейлить сборку). Также важно не хранить секреты внутри образа: они должны инжектироваться через переменные окружения при запуске, а не через ENV в Dockerfile.
Использование GitHub Container Registry (GHCR). Реестр образов GitHub Container Registry (GHCR) — это альтернатива Docker Hub, которая тесно интегрирована с платформой GitHub. Преимущества: единая система аутентификации (используется тот же токен, что и для доступа к репозиторию), поддержка детальных прав доступа на уровне пакетов и неограниченное хранилище для публичных образов. Для авторизации в GHCR используется стандартный токен доступа (GITHUB_TOKEN) с правами write:packages. Адрес реестра: ghcr.io/OWNER/IMAGE_NAME. Использование GHCR упрощает инфраструктуру, так как разработчикам не нужно заводить отдельные аккаунты в Docker Hub, а секреты для логина минимальны — достаточно одного PAT (Personal Access Token). В воркфлоу это выглядит как docker login ghcr.io -u ${{ github.actor }} --password-stdin.
Настройка Nginx как Reverse Proxy. Часто на сервере приложение работает на порту 3000 или 8080, а пользователи заходят по стандартному 80-му (HTTP) или 443-му (HTTPS) порту. Для маршрутизации трафика используется Reverse Proxy, чаще всего Nginx. Он принимает запросы извне и проксирует их к контейнеру. Настройка Nginx требует минимальной конфигурации. В пайплайне можно автоматизировать перезагрузку Nginx при изменении конфигурации. Для безопасности обязательно настраивать HTTPS: можно использовать Let's Encrypt и Certbot для автоматического получения SSL-сертификатов. В рамках CI/CD реверс-прокси обычно настраивается один раз вручную или через инфраструктурный код (Terraform, Ansible), а обновление приложений идет без участия Nginx.
Модуль 5. Полный пример пайплайна и работа с реестрами
Пример Dockerfile и docker-compose для Node.js. Рассмотрим полный рабочий пример для Node.js-приложения. Dockerfile использует двухэтапную сборку: на первом этапе (builder) устанавливаем зависимости и строим код (TypeScript), на втором (production) копируем только результат сборки и выполняем npm ci --only=production для установки продакшн-зависимостей. Это уменьшает размер образа со 150 до 80 МБ. Для запуска в продакшне используется docker-compose.yml, где описываются сервисы: само приложение (app), база данных (postgres) и кэш (redis). Compose определяет переменные среды, тома для сохранения данных базы и сети для взаимодействия сервисов. Такой подход делает приложение самодостаточным и легко развертываемым одной командой.
Пайплайн деплоя на VPS: пошаговый анализ YAML. Полноценный файл .github/workflows/deploy.yml состоит из трех джобов. Джоба 1 (Test): проверяет код на ошибки (npm run lint, npm test). Джоба 2 (Build): запускается needs: test, собирает образ, используя docker/build-push-action с тегом sha-${{ github.sha }}, и пушит его в GHCR. Для кэширования добавлены параметры cache-from и cache-to. Джоба 3 (Deploy): использует appleboy/ssh-action. На сервере выполняются команды: логин в реестр, переход в папку проекта, docker compose pull (подтягивание образа по тегу latest или конкретному SHA), docker compose up -d и проверка /health. Такая структура обеспечивает скорость, безопасность и надежность деплоя.
Интеграция с AWS, Azure и облачными сервисами. Помимо VPS, деплой часто осуществляется в публичные облака. AWS: образы загружаются в Amazon ECR (Elastic Container Registry), а деплой осуществляется в ECS Fargate (serverless контейнеры) или EKS (Kubernetes). Azure: используется Azure Container Registry (ACR) и сервис Azure App Service или AKS. В GitHub Actions для этого существуют готовые экшены (aws-actions/amazon-ecr-login, azure/docker-login). Процесс аналогичен VPS: сборка, пуш в облачный реестр, затем запуск через API облачного провайдера. Это дает преимущества: автоматическое масштабирование, управляемые базы данных и высокая доступность. Выбор между VPS и облаком зависит от бюджета, требований к контролю инфраструктуры и необходимости использования managed-сервисов.
Мониторинг и Observability пайплайнов. После настройки пайплайна важно видеть, что происходит в продакшне. Это включает мониторинг самих раннеров GitHub Actions и логирование приложений. В экосистеме Docker и DevOps стандартом является связка Prometheus + Grafana для сбора метрик и визуализации, а также ELK Stack (Elasticsearch, Logstash, Kibana) для централизованного сбора логов. В пайплайне можно добавить шаги для отправки уведомлений в Slack или Telegram о статусе деплоя (успешно/неуспешно). Это повышает прозрачность процесса. Использование GitHub Actions позволяет легко интегрировать Grafana Cloud или Datadog для мониторинга работы самого приложения, собирая метрики из контейнеров через экспортеры.
GitOps и будущее CI/CD. GitOps — это эволюция CI/CD, где Git становится единственным источником истины (single source of truth) не только для кода, но и для всей конфигурации инфраструктуры. Вместо того чтобы SSH подключался к серверу и выполнял команды, используется агент (например, ArgoCD или Flux), который работает внутри кластера Kubernetes и синхронизирует состояние кластера с манифестами, лежащими в Git-репозитории. Пайплайн CI собирает образ и кладет его в реестр, а агент CD автоматически подтягивает новые изменения, описанные в манифестах. Это значительно повышает безопасность (не нужны SSH-ключи на серверах) и упрощает откаты (достаточно откатить коммит в Git). Внедрение GitOps — следующий шаг для команд, переходящих на Kubernetes.
Заключение и следующие шаги
Итоги курса. Мы прошли полный путь от теории CI/CD до практической реализации пайплайна для full-stack приложения. Вы научились контейнеризировать приложения с помощью Docker, писать оптимизированные Dockerfile, настраивать автоматические сборки и тесты в GitHub Actions, а также безопасно доставлять обновления на удаленные серверы без остановки сервиса. Эти навыки являются базовыми для современного разработчика и инженера, позволяя сократить время релиза с часов до минут и избавиться от рутины ручных деплоев.
Дальнейшее развитие и ресурсы. Для углубления знаний рекомендуем изучить оркестрацию контейнеров с помощью Kubernetes, который позволяет управлять тысячами контейнеров в кластере. Также полезно освоить инструменты Infrastructure as Code (IaC), такие как Terraform (для создания серверов в облаке) и Ansible (для настройки серверов). Не забывайте про практику: создайте свой пет-проект и внедрите туда описанный пайплайн. Изучайте документации Docker, GitHub Actions и Kubernetes — они постоянно обновляются.