Миграции БД с Atlas: GitOps для schema
Практическое руководство по использованию Atlas для декларативных миграций схемы и интеграции в CI/CD. Выполните от начала до конца за ~60–90 минут на машине с 4 ГБ ОЗУ.
Статья была полезной?
Практическое руководство по использованию Atlas для декларативных миграций схемы и интеграции в CI/CD. Выполните от начала до конца за ~60–90 минут на машине с 4 ГБ ОЗУ.
Статья была полезной?
ariga/atlas:1.8.0, ~28 MB.postgres:15, ~175 MB.Atlas — инструмент от Ariga для управления схемой базы данных декларативно и миграциями в режиме GitOps. Atlas 1.8.0 (релиз 2026) сочетает в себе синтез схемы в формате HCL/YAML, diff-механизм и apply-операции, ориентированные на reproducible workflow. Он поддерживает PostgreSQL, MySQL и SQLite и оптимизирован для интеграции в CI/CD и pull request-ревью.

Схема работы Atlas: репозиторий -> diff -> apply
Цель шага — описать базовую схему декларативно в репозитории и синхронизировать с локальной БД. Требуемое время: 10–15 минут. Команды ниже показаны для atlas CLI 1.8.0 (релиз 2026).
Команда: инициализация проекта и создание файла schema.hcl
mkdir atlas-project && cd atlas-project
cat > schema.hcl <<'HCL'
env "dev" {
url = "postgres://postgres:postgres@localhost:5432/devdb?sslmode=disable"
}
schema "app" {
table "users" {
column "id" { type = "bigserial" }
column "email" { type = "varchar(255)" }
column "created_at" { type = "timestamptz" }
primary_key { columns = ["id"] }
}
}
HCLОбъяснение: файл schema.hcl описывает окружение dev и схему app с таблицей users. Atlas хранит структуру в виде HCL, что удобно для ревью и diff в git.
Ожидаемый вывод при проверки схемы локально:
$ docker run --rm -v $(pwd):/work -w /work ariga/atlas:1.8.0 atlas schema inspect -e dev --format json
{
"kind": "schema",
"name": "app",
"tables": [
{ "name": "users", "columns": [ ... ] }
]
}Типичная ошибка и фикс:
Ошибка: could not connect to postgres: dial tcp 127.0.0.1:5432: connect: connection refused
Фикс: убедитесь, что контейнер PostgreSQL запущен:
docker run -d --name pg-test -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres:15
(ожидание старта ~3-6 с)Примечание по времени: запуск контейнера PostgreSQL обычно занимает 3–10 секунд на SSD; если база поднимается медленно, подождите 5–15 секунд перед выполнением команды inspect.

Фрагмент schema.hcl в редакторе
Цель шага — сгенерировать diff между declarative schema и реальной БД, создать миграцию и применить её. Время: 15–25 минут включая ревью миграции.
Команда: сгенерировать diff и создать миграцию
# создать миграцию из текущих изменений в schema.hcl
docker run --rm -v $(pwd):/work -w /work ariga/atlas:1.8.0 atlas migrate diff --dir file://migrations -e dev --format sql -o migration.sqlОбъяснение: команда создаёт SQL-файл в каталоге migrations с конкретными шагами DDL. Путь file://migrations — локальный каталог в репозитории, который попадёт в git и будет ревьються.
Ожидаемый успешный вывод:
Generating migration: /work/migrations/20260401_0001_add_users_table.sql
---
CREATE TABLE "users" (
"id" bigserial PRIMARY KEY,
"email" varchar(255),
"created_at" timestamptz
);
---
Success: migration createdТипичная ошибка и её исправление:
Ошибка: directory "/work/migrations" does not exist
Фикс: создайте каталог миграций перед запуском:
mkdir -p migrations
и повторите команду.Команда: применить миграцию (dry run и потом apply)
# dry-run (покажет SQL, но не применит)
docker run --rm -v $(pwd):/work -w /work ariga/atlas:1.8.0 atlas migrate apply -e dev --dir file://migrations --dry-run
# если всё верно, применяем:
docker run --rm -v $(pwd):/work -w /work ariga/atlas:1.8.0 atlas migrate apply -e dev --dir file://migrationsОжидаемый вывод при dry-run:
-- dry run SQL
CREATE TABLE "users" (
"id" bigserial PRIMARY KEY,
"email" varchar(255),
"created_at" timestamptz
);
-- end dry runОжидаемый вывод при реальном apply:
Applying migration: 20260401_0001_add_users_table.sql
Applied successfullyТипичная ошибка и фиксы:
Ошибка: migration is already applied
Фикс: проверьте таблицу миграций (по умолчанию atlas_schema_revisions). Если миграция частично применена, выполните откат вручную или создайте новую миграцию с откатом.
Ошибка: permission denied for schema public
Фикс: проверьте пользователя подключения в URL: предоставьте CREATE привилегии для роли, используемой Atlas, или используйте роль с достаточными правами.Цель шага — интегрировать проверку diffs и тестовый apply в CI. Время: 20–30 минут на настройку GitHub Actions workflow и тестирование в CI.
Подход: в PR запускать job, которая поднимает ephemeral PostgreSQL контейнер, запускает atlas migrate diff и проверяет, что новые SQL-миграции соответствуют ожиданиям (no drift). Если diff обнаружен — job должен провалиться и потребовать обновления миграций.
Пример workflow (GitHub Actions):
name: atlas-migrations
on: [pull_request]
jobs:
check-schema:
runs-on: ubuntu-22.04
services:
postgres:
image: postgres:15
ports: ['5432:5432']
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd "pg_isready -U postgres" --health-interval 5s --health-timeout 2s --health-retries 10
steps:
- uses: actions/checkout@v4
- name: Run atlas diff
run: |
docker run --rm -v ${{ github.workspace }}:/work -w /work ariga/atlas:1.8.0 /bin/sh -c \
"sleep 5 && atlas migrate diff --dir file://migrations -e dev --format sql > /tmp/diff.sql || true && test -s /tmp/diff.sql && (echo 'DRIFT FOUND' && exit 1) || echo 'No drift'"Объяснение: job поднимает PostgreSQL, монтирует репозиторий и выполняет diff. Если diff возвращает содержимое, значит схема в коде и БД не совпадают — CI провалит сборку.
Ожидаемый вывод CI при успехе:
No driftОжидаемый вывод при обнаружении расхождения:
DRIFT FOUND
Error: Process completed with exit code 1.Типичные ошибки и фиксы в CI:
Ошибка: pg_isready health check timeouts
Фикс: увеличьте --health-retries или добавьте задержку перед запуском atlas (sleep 5-15). На тяжёлых runner-ах запуск Postgres может занимать 10-20 с.
Ошибка: каталога migrations нет в build-артефакте
Фикс: проверьте, что migrations заинклюдены в репозитории и не игнорируются .gitignore.Цель — показать безопасный путь применения миграций в production через CD pipeline. Время: 15–30 минут для примера и конфигурации шага deploy.
Практика: разделите CI (проверка) и CD (применение). CD-runner должен иметь ограниченные права и работать по цепочке утверждений: PR -> main -> manual approval -> deploy.
Пример шага в CD pipeline:
jobs:
deploy:
runs-on: ubuntu-22.04
needs: [build, check-schema]
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Apply migrations to production
env:
DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
run: |
docker run --rm -v ${{ github.workspace }}:/work -w /work ariga/atlas:1.8.0 /bin/sh -c \
"atlas migrate apply --dir file://migrations -e prod"Объяснение: URL к production хранится в секретах CI (GitHub Secrets). Перед apply должен сработать manual approval (environment protection rules) и проверка, что migrations в main совпадают с ожидаемыми.
Типичная ошибка и решение:
Ошибка: secrets.PROD_DATABASE_URL отсутствует
Фикс: добавьте секрет в репозиторий или организации и протестируйте в staging перед production.
Ошибка: apply зависает при блокировке DDL
Фикс: используйте транзакции и тестируйте сценарии блокировок в staging, применяйте миграции в maintenance window с мониторингом.Рекомендуется включать в CD step логирование выполнения миграций и систему отката (backup/pg_dump) перед apply для production: время создания дампа ~10–60 с в зависимости от объема данных.
Atlas и Flyway решают задачу миграций, но подходы различаются. Flyway (стабильная ветка 9.x, релизы 2023–2025) ориентирован на миграции как серию SQL-скриптов, выполняемых последовательно. Atlas фокусируется на декларативной схеме и генерации миграций через diff, что снижает вероятность human-error при создании DDL.
Когда выбирать Flyway: если команда уже имеет десятки ручных версий SQL и нужна минимальная инфраструктура — Flyway быстрее встраивается. Когда выбирать Atlas: если вы хотите GitOps workflow, генерацию миграций и более предсказуемый diff-process.
golang-migrate (релизы активны 2020–2025) — минималистичный инструмент для запуска SQL миграций, часто используется в приложениях на Go. Он компактен и удобен для включения в приложение, но не предоставляет декларативного представления схемы и генерации diff.
Храните schema.hcl в корне репозитория в каталоге db/schema или infrastructure/db. Зафиксируйте правило: любые изменения схемы должны сопровождаться генерацией миграции через atlas migrate diff и созданием Pull Request. Так обеспечивается единый источник правды и независимая проверка в CI. Файлы HCL удобны для машинного парсинга и для визуального ревью. Включите форматы и линтеры в pre-commit, чтобы избежать форматных шумов.
Если в production есть ручные изменения, начните с инвентаризации: используйте atlas schema inspect, чтобы снять текущую схему и сохранить её в репозитории как baseline. Создайте миграцию, приводящую репозиторий к состоянию production (baseline migration), и пометьте её как applied. В CI добавьте проверки, чтобы новые миграции не противоречили baseline. Такой подход требует планирования и тестов в staging перед конвертацией в GitOps workflow.
Diff основан на структурной модели схемы. Atlas стремится к детерминированному выходу, но различия в DDL (например, неявные значения по умолчанию или порядок столбцов) могут приводить к шуму. Решения: нормализуйте схему перед diff (используйте atlas schema inspect --format hcl для стандартизации), настройте процесс ревью, чтобы фильтровать незначимые изменения, и тестируйте генерацию миграций в локальных environment перед PR.
Можно хранить миграции рядом с кодом приложения (mono-repo) или в отдельном репозитории-инфраструктуре. Mono-repo даёт простую координацию изменений и atomic commits (код + миграция), но может усложнить права доступа. Отдельный репозиторий удобен для централизованного контроля и общего процесса CD. Решение зависит от команды: если deploy приложения и миграции синхронны, храните их рядом; если команды ролей разные, рассмотрите выделенный repo для миграций и schema.hcl.
Время отката зависит от объёма данных и характера изменения. Простое удаление индекса — ~1–3 секунды; откат DROP COLUMN с миграцией данных может занимать минуты или часы. Всегда планируйте backup: pg_dump/pg_basebackup перед применением миграций. Для крупных таблиц используйте стратегию zero-downtime: создание новой колонки, фоновые миграции для копирования данных и переключение приложений. Тестируйте откат в staging, чтобы измерить реальные времена и подготовить план rollforward/rollback.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…