Files
airflow-greenplum/plans/dockerfile-improvements.md
T

490 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План улучшения Dockerfile и docker-compose.yml
## Обзор
Документ описывает план улучшения Dockerfile для Airflow и его интеграции с docker-compose.yml на основе анализа best practices.
## Согласованные изменения
✅ Переименовать `Dockerfile``Dockerfile.airflow`
✅ Обновить `build: .``build: { context: ., dockerfile: Dockerfile.airflow }`
✅ Добавить YAML anchors для устранения дублирования конфигурации
✅ Добавить healthcheck для airflow-webserver
✅ Исправить расположение requirements.txt в Dockerfile
✅ Добавить LABEL в Dockerfile
✅ Добавить `USER airflow` после установки зависимостей
✅ Добавить проверку `pip check`
✅ Переименовать контейнеры (`gp_airflow_web``gp_airflow_webserver`, `gp_airflow_sch``gp_airflow_scheduler`)
---
## Часть 1: Изменения в Dockerfile
### Текущее состояние (Dockerfile)
```dockerfile
FROM apache/airflow:2.9.2
COPY airflow/requirements.txt /requirements.txt
RUN pip install --no-cache-dir -r /requirements.txt
```
### Новое состояние (Dockerfile.airflow)
```dockerfile
# Apache Airflow с дополнительными зависимостями для Greenplum
FROM apache/airflow:2.9.2
LABEL maintainer="your-email@example.com"
LABEL description="Airflow with Greenplum and Pandas dependencies"
LABEL version="1.0"
# Копируем requirements в стандартное расположение
COPY airflow/requirements.txt /opt/airflow/requirements.txt
# Устанавливаем зависимости
RUN pip install --no-cache-dir -r /opt/airflow/requirements.txt \
&& pip check \
&& rm -rf /tmp/pip-*
# Переключаемся на пользователя airflow
USER airflow
WORKDIR /opt/airflow
```
### Обоснование изменений:
1. **LABEL** - стандартная практика для документирования образов
2. **`/opt/airflow/requirements.txt`** - стандартное расположение для Airflow
3. **`pip check`** - проверка совместимости установленных пакетов
4. **`USER airflow`** - безопасность и соответствие best practices
5. **`WORKDIR /opt/airflow`** - явное указание рабочей директории
---
## Часть 2: Изменения в docker-compose.yml
### Основные изменения:
1. **Добавить YAML anchors** для устранения дублирования
2. **Обновить build** для всех Airflow сервисов
3. **Добавить healthcheck** для airflow-webserver
4. **Добавить комментарии** для пояснения сокращений в именах контейнеров
### Структура YAML anchors:
```yaml
x-airflow-common-env: &airflow-env
TZ: ${TZ:-Europe/Moscow}
AIRFLOW__CORE__LOAD_EXAMPLES: "False"
AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: postgresql+psycopg2://${PG_USER}:${PG_PASSWORD}@pgmeta:5432/${PG_DB}
AIRFLOW__WEBSERVER__SECRET_KEY: ${AIRFLOW__WEBSERVER__SECRET_KEY}
AIRFLOW_CONN_GREENPLUM_CONN: postgresql://${GP_USER}:${GP_PASSWORD}@greenplum:${GP_PORT:-5432}/${GP_DB}
AIRFLOW_CONN_BOOKINGS_DB: postgresql://${BOOKINGS_DB_USER}:${BOOKINGS_DB_PASSWORD}@bookings-db:5432/demo
x-airflow-common-volumes: &airflow-volumes
- ./airflow/dags:/opt/airflow/dags
- ./sql:/sql:ro
- airflow_data:/opt/airflow/data
x-airflow-common-depends: &airflow-depends
pgmeta:
condition: service_healthy
greenplum:
condition: service_healthy
airflow-init:
condition: service_completed_successfully
```
### Изменения для airflow-webserver:
```yaml
airflow-webserver:
build:
context: .
dockerfile: Dockerfile.airflow
image: airflow-custom:latest
container_name: gp_airflow_webserver
env_file: .env
environment:
<<: *airflow-env
command: airflow webserver
ports:
- "8080:8080"
volumes:
<<: *airflow-volumes
# requirements.txt монтируется как volume для удобства разработки
# При изменении зависимостей не требуется пересборка образа
- ./airflow/requirements.txt:/opt/airflow/requirements.txt
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 5
start_period: 40s
depends_on:
<<: *airflow-depends
```
### Изменения для airflow-scheduler:
```yaml
airflow-scheduler:
build:
context: .
dockerfile: Dockerfile.airflow
image: airflow-custom:latest
container_name: gp_airflow_scheduler
env_file: .env
environment:
<<: *airflow-env
command: airflow scheduler
volumes:
<<: *airflow-volumes
- ./airflow/requirements.txt:/opt/airflow/requirements.txt
depends_on:
<<: *airflow-depends
```
### Изменения для airflow-init:
```yaml
airflow-init:
build:
context: .
dockerfile: Dockerfile.airflow
image: airflow-custom:latest
# Имя контейнера закомментировано (одноразовый сервис)
user: "0"
env_file: .env
environment:
<<: *airflow-env
volumes:
<<: *airflow-volumes
command: >
bash -lc "
set -e;
mkdir -p /opt/airflow/data && chown -R airflow:root /opt/airflow/data;
for i in {1..30}; do
su -s /bin/bash airflow -c \"PATH='/home/airflow/.local/bin:$${PATH}' airflow db migrate\" && break || echo 'waiting for pgmeta' && sleep 3;
done;
su -s /bin/bash airflow -c \"PATH='/home/airflow/.local/bin:$${PATH}' airflow users create --username ${AIRFLOW_USER} --password ${AIRFLOW_PASSWORD} --firstname Admin --lastname User --role Admin --email admin@example.org\" || true
"
depends_on:
pgmeta:
condition: service_healthy
```
---
## Часть 3: Влияние переименования контейнеров
### Важно: Переименование контейнеров
При переименовании контейнеров (`gp_airflow_web``gp_airflow_webserver`, `gp_airflow_sch``gp_airflow_scheduler`) необходимо учитывать:
1. **Имена сервисов в docker-compose.yml остаются без изменений**
- `airflow-webserver`, `airflow-scheduler`, `airflow-init` - это имена сервисов
- Они используются в командах `docker-compose logs`, `docker-compose restart` и т.д.
- Эти имена НЕ меняются
2. **Имена контейнеров меняются**
- `gp_airflow_web``gp_airflow_webserver`
- `gp_airflow_sch``gp_airflow_scheduler`
- Они используются в командах `docker exec`, `docker inspect`, `docker logs`
3. **Проверка использования старых имён контейнеров**
```bash
# Поиск упоминаний старых имён в скриптах
grep -r "gp_airflow_web" .
grep -r "gp_airflow_sch" .
```
4. **Обновление Makefile (если используется)**
- Проверить команды, которые используют старые имена контейнеров
- Пример: `make logs` может использовать `docker-compose logs airflow-webserver` (это корректно)
5. **Обновление документации**
- Обновить все упоминания имён контейнеров в README.md, TESTING.md
- Обновить примеры команд в документации
---
## Часть 4: План тестирования изменений
### Этап 1: Подготовка окружения
1. **Остановить текущие контейнеры**
```bash
make down
```
2. **Удалить старые образы (опционально)**
```bash
docker rmi airflow-custom:latest
```
3. **Проверить наличие .env файла**
```bash
ls -la .env
# Если отсутствует, скопировать из .env.example
cp .env.example .env
```
### Этап 2: Сборка новых образов
1. **Собрать образы с новым Dockerfile**
```bash
docker-compose build
```
2. **Проверить успешность сборки**
```bash
docker images | grep airflow-custom
```
3. **Проверить наличие LABEL**
```bash
docker inspect airflow-custom:latest | grep -A 10 "Labels"
```
### Этап 3: Запуск сервисов
1. **Запустить весь стек**
```bash
make up
```
2. **Проверить статус контейнеров**
```bash
docker-compose ps
```
3. **Проверить логи инициализации**
```bash
docker-compose logs airflow-init
```
### Этап 4: Проверка healthcheck
1. **Проверить healthcheck для airflow-webserver**
```bash
docker inspect gp_airflow_webserver | grep -A 20 "Health"
```
2. **Дождаться healthy статуса**
```bash
watch -n 2 'docker inspect --format="{{.State.Health.Status}}" gp_airflow_webserver'
```
### Этап 5: Функциональное тестирование
1. **Проверить доступ к Airflow UI**
- Открыть http://localhost:8080
- Проверить авторизацию (использовать креды из .env)
- Проверить наличие DAG'ов в списке
2. **Проверить запуск DAG'ов**
- Выбрать любой DAG (например, `csv_to_greenplum`)
- Запустить вручную через UI
- Проверить успешность выполнения задач
3. **Проверить подключения к БД**
- Проверить Admin → Connections
- Убедиться, что `greenplum_conn` и `bookings_db` доступны
- Проверить Test Connection для каждого подключения
4. **Проверить логи scheduler**
```bash
docker-compose logs airflow-scheduler | tail -50
```
### Этап 6: Проверка использования старых имён контейнеров
1. **Поиск упоминаний старых имён в проекте**
```bash
grep -r "gp_airflow_web" . --exclude-dir=.git --exclude-dir=__pycache__
grep -r "gp_airflow_sch" . --exclude-dir=.git --exclude-dir=__pycache__
```
2. **Проверка Makefile**
```bash
grep -E "gp_airflow_web|gp_airflow_sch" Makefile
```
3. **Проверка документации**
```bash
grep -r "gp_airflow_web" README.md TESTING.md AGENTS.md docs/
grep -r "gp_airflow_sch" README.md TESTING.md AGENTS.md docs/
```
4. **Обновление найденных упоминаний**
- Заменить `gp_airflow_web` на `gp_airflow_webserver`
- Заменить `gp_airflow_sch` на `gp_airflow_scheduler`
- Обновить примеры команд в документации
### Этап 7: Тестирование требований
1. **Проверить установленные пакеты**
```bash
docker exec gp_airflow_webserver pip list | grep -E "psycopg2|pandas"
```
2. **Проверить совместимость пакетов**
```bash
docker exec gp_airflow_webserver pip check
```
3. **Проверить пользователя внутри контейнера**
```bash
docker exec gp_airflow_webserver whoami
# Ожидаемый результат: airflow
```
### Этап 8: Тестирование изменений requirements.txt
1. **Добавить тестовый пакет в requirements.txt**
```bash
echo "requests==2.31.0" >> airflow/requirements.txt
```
2. **Перезапустить контейнеры**
```bash
docker-compose restart airflow-webserver airflow-scheduler
```
3. **Проверить установку пакета**
```bash
docker exec gp_airflow_webserver pip list | grep requests
```
4. **Удалить тестовый пакет**
```bash
# Вернуть исходный requirements.txt
git checkout airflow/requirements.txt
```
### Этап 9: Регрессионное тестирование
1. **Запустить существующие тесты**
```bash
make test
```
2. **Проверить smoke-тесты DAG**
```bash
uv run pytest tests/test_dags_smoke.py -v
```
3. **Проверить тесты helpers**
```bash
uv run pytest tests/test_greenplum_helpers.py -v
```
### Этап 10: Проверка после перезапуска
1. **Полный перезапуск стека**
```bash
make down
make up
```
2. **Проверить сохранность данных**
- Проверить наличие DAG'ов в UI
- Проверить историю запусков DAG'ов
- Проверить подключения к БД
3. **Проверить логи на наличие ошибок**
```bash
docker-compose logs airflow-webserver | grep -i error
docker-compose logs airflow-scheduler | grep -i error
# Обратите внимание: имена сервисов не изменились, только имена контейнеров
```
---
## Часть 5: Критерии успеха
### Функциональные требования:
- ✅ Все контейнеры успешно запускаются
- ✅ Airflow UI доступен на http://localhost:8080
- ✅ Авторизация работает корректно
- ✅ Все DAG'ы отображаются в UI
- ✅ DAG'и успешно выполняются
- ✅ Подключения к Greenplum и bookings-db работают
- ✅ Healthcheck для airflow-webserver работает корректно
### Технические требования:
- ✅ Образ собирается без ошибок
- ✅ LABEL присутствуют в образе
- ✅ Пакеты устанавливаются от пользователя airflow
- ✅ `pip check` не возвращает ошибок
- ✅ requirements.txt монтируется как volume
- ✅ YAML anchors работают корректно
- ✅ Нет дублирования конфигурации
### Требования к совместимости:
- ✅ Существующие тесты проходят успешно
- ✅ Данные сохраняются после перезапуска
- ✅ История запусков DAG'ов сохраняется
- ✅ Подключения к БД работают как раньше
---
## Часть 6: Откат изменений
Если изменения вызывают проблемы, план отката:
1. **Остановить контейнеры**
```bash
make down
```
2. **Вернуть старые файлы**
```bash
git checkout Dockerfile docker-compose.yml
```
3. **Удалить новый образ**
```bash
docker rmi airflow-custom:latest
```
4. **Перезапустить стек**
```bash
make up
```
---
## Часть 7: Документация
После успешного внедрения изменений необходимо обновить:
1. **README.md** - добавить информацию о новом Dockerfile
2. **AGENTS.md** - обновить инструкции для агентов
3. **Комментарии в docker-compose.yml** - добавить пояснения к YAML anchors
---
## Резюме
План включает:
- 2 файла для изменения: `Dockerfile` → `Dockerfile.airflow`, `docker-compose.yml`
- 10 этапов тестирования
- 12 функциональных критериев успеха
- План отката на случай проблем
- Переименование контейнеров для улучшения читаемости
- Проверка использования старых имён контейнеров в проекте
### Важные замечания:
1. **Имена сервисов НЕ меняются** - `airflow-webserver`, `airflow-scheduler`, `airflow-init`
2. **Имена контейнеров меняются** - `gp_airflow_web` → `gp_airflow_webserver`, `gp_airflow_sch` → `gp_airflow_scheduler`
3. **Необходимо проверить** использование старых имён контейнеров в скриптах и документации
4. **Makefile команды** используют имена сервисов, поэтому они продолжат работать без изменений
Все изменения следуют best practices для Docker и Airflow, сохраняют обратную совместимость и не требуют изменений в DAG'ах.