Opções para rodar localmente

OpçãoComplexidadeQuando usar
airflow standaloneMínimaExploração rápida, SQLite + SequentialExecutor
Docker Compose oficialMédiaDesenvolvimento fiel ao ambiente de produção
Docker Compose customizadoAltaControle total sobre versões e configurações

Quickstart com airflow standalone

Sem Docker, para exploração rápida:

pip install "apache-airflow==2.9.3" \
  --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-2.9.3/constraints-3.11.txt"
 
export AIRFLOW_HOME=~/airflow
airflow standalone
# UI disponível em http://localhost:8080
# Usuário: admin | Senha: impressa no terminal

Usa SQLite como backend e SequentialExecutor: não adequado para produção ou testes de paralelismo.

Docker Compose (setup recomendado)

Baixar o arquivo oficial

mkdir airflow-local && cd airflow-local
curl -LfO 'https://airflow.apache.org/docs/apache-airflow/2.9.3/docker-compose.yaml'

Estrutura de pastas

mkdir -p ./dags ./logs ./plugins ./config
echo -e "AIRFLOW_UID=$(id -u)" > .env
airflow-local/
├── docker-compose.yaml
├── .env                    # AIRFLOW_UID, segredos
├── dags/                   # seus DAGs (montado no container)
├── logs/                   # logs de task (montado)
├── plugins/                # plugins customizados
└── config/
    └── airflow.cfg         # overrides de configuração (opcional)

Inicializar o banco e subir

# Inicializa o banco de metadados e cria o usuário admin
docker compose up airflow-init
 
# Sobe toda a stack
docker compose up -d

A UI fica disponível em http://localhost:8080 (usuário: airflow / senha: airflow).

Serviços do Docker Compose padrão

graph TB
    subgraph Airflow Stack
        WS[airflow-webserver\n:8080]
        SCH[airflow-scheduler]
        WK[airflow-worker]
        TRG[airflow-triggerer]
        INIT[airflow-init]
    end
    PG[(postgres\n:5432)]
    RD[(redis\n:6379)]

    SCH --> RD
    WK --> RD
    WS --> PG
    SCH --> PG
    WK --> PG
    TRG --> PG

O compose padrão usa CeleryExecutor com Redis como broker e PostgreSQL como metadata DB.

Variáveis de ambiente essenciais

# .env
AIRFLOW_UID=50000
 
# Chave de criptografia para conexões (gerar uma vez com: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())")
AIRFLOW__CORE__FERNET_KEY=sua_chave_aqui
 
# Backend de metadados
AIRFLOW__DATABASE__SQL_ALCHEMY_CONN=postgresql+psycopg2://airflow:airflow@postgres/airflow
 
# Executor
AIRFLOW__CORE__EXECUTOR=CeleryExecutor
 
# Broker Celery
AIRFLOW__CELERY__BROKER_URL=redis://:@redis:6379/0
AIRFLOW__CELERY__RESULT_BACKEND=db+postgresql://airflow:airflow@postgres/airflow
 
# Desabilitar exemplos incluídos no Airflow
AIRFLOW__CORE__LOAD_EXAMPLES=False
 
# Fuso horário padrão
AIRFLOW__CORE__DEFAULT_TIMEZONE=America/Sao_Paulo
 
# Número de DAGs parseados em paralelo pelo scheduler
AIRFLOW__SCHEDULER__PARSING_PROCESSES=2

Docker Compose customizado (produção-like)

Para ter mais controle, crie um docker-compose.yml próprio:

x-airflow-common: &airflow-common
  image: apache/airflow:2.9.3-python3.11
  environment:
    AIRFLOW__CORE__EXECUTOR: CeleryExecutor
    AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@postgres/airflow
    AIRFLOW__CELERY__BROKER_URL: redis://:@redis:6379/0
    AIRFLOW__CELERY__RESULT_BACKEND: db+postgresql://airflow:airflow@postgres/airflow
    AIRFLOW__CORE__FERNET_KEY: ${AIRFLOW__CORE__FERNET_KEY}
    AIRFLOW__CORE__LOAD_EXAMPLES: "false"
    AIRFLOW__WEBSERVER__SECRET_KEY: ${AIRFLOW__WEBSERVER__SECRET_KEY}
  volumes:
    - ./dags:/opt/airflow/dags
    - ./logs:/opt/airflow/logs
    - ./plugins:/opt/airflow/plugins
    - ./config/airflow.cfg:/opt/airflow/airflow.cfg
  user: "${AIRFLOW_UID:-50000}:0"
  depends_on:
    postgres:
      condition: service_healthy
    redis:
      condition: service_healthy
 
services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: airflow
      POSTGRES_PASSWORD: airflow
      POSTGRES_DB: airflow
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "airflow"]
      interval: 10s
      retries: 5
    volumes:
      - postgres_data:/var/lib/postgresql/data
 
  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      retries: 5
 
  airflow-webserver:
    <<: *airflow-common
    command: webserver
    ports:
      - "8080:8080"
    healthcheck:
      test: ["CMD", "curl", "--fail", "http://localhost:8080/health"]
      interval: 30s
      retries: 5
 
  airflow-scheduler:
    <<: *airflow-common
    command: scheduler
 
  airflow-worker:
    <<: *airflow-common
    command: celery worker
    deploy:
      replicas: 2  # dois workers em paralelo
 
  airflow-triggerer:
    <<: *airflow-common
    command: triggerer
 
  airflow-init:
    <<: *airflow-common
    command: >
      bash -c "
        airflow db migrate &&
        airflow users create
          --username admin
          --password admin
          --firstname Admin
          --lastname User
          --role Admin
          --email [email protected]
      "
 
volumes:
  postgres_data:

Instalar dependências Python customizadas

Para adicionar pacotes (providers, bibliotecas de negócio), crie uma imagem derivada:

# Dockerfile
FROM apache/airflow:2.9.3-python3.11
 
USER airflow
COPY requirements.txt /requirements.txt
RUN pip install --no-cache-dir -r /requirements.txt
# requirements.txt
apache-airflow-providers-google==10.15.0
apache-airflow-providers-amazon==8.20.0
apache-airflow-providers-databricks==6.6.0
pandas==2.0.3
pyarrow==14.0.1
# No docker-compose.yml, substituir a imagem base:
# image: apache/airflow:2.9.3-python3.11
# por:
# build: .

Comandos úteis no dia a dia

# Ver status dos containers
docker compose ps
 
# Logs do scheduler
docker compose logs -f airflow-scheduler
 
# Abrir shell em um container
docker compose exec airflow-scheduler bash
 
# Listar DAGs
docker compose exec airflow-scheduler airflow dags list
 
# Testar uma task específica
docker compose exec airflow-scheduler \
  airflow tasks test meu_dag nome_da_task 2026-01-01
 
# Disparar DAG manualmente
docker compose exec airflow-scheduler \
  airflow dags trigger meu_dag
 
# Escalar workers
docker compose up -d --scale airflow-worker=4
 
# Parar tudo (mantém volumes)
docker compose down
 
# Parar e apagar volumes (reset completo)
docker compose down -v

airflow.cfg: principais configurações

[core]
dags_folder = /opt/airflow/dags
load_examples = False
default_timezone = America/Sao_Paulo
parallelism = 32          # máximo de tasks simultâneas em toda a instância
max_active_tasks_per_dag = 16
max_active_runs_per_dag = 4
 
[scheduler]
dag_dir_list_interval = 30   # com que frequência escanear a pasta de DAGs (segundos)
parsing_processes = 2        # processos paralelos de parsing
 
[webserver]
workers = 4                  # gunicorn workers para o webserver
expose_config = True         # permite ver airflow.cfg na UI (cuidado em prod)

Ver também: airflow | airflow-dag-desenvolvimento | airflow-deploy-kubernetes | docker-compose | Docker | docker-conceitos-fundamentais