Skip to content
flrodrigues21Public

About

Laboratório de engenharia e governança de dados com pipelines orientados por metadados, Airflow, PostgreSQL, MinIO, Docker e OpenMetadata.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

ELT Lab

Ambiente local de ELT (Extract, Load, Transform) com Apache Airflow, MinIO e PostgreSQL via Docker.

Basta clonar e rodar .\setup.ps1 para ter o lab completo funcionando.


Setup (3 passos)

# 1. Clonar
git clone https://github.com/flrodrigues21/elt.git
cd elt

# 2. Subir tudo (gera .env com senhas seguras automaticamente)
.\setup.ps1

# 3. Rodar o pipeline
# Abra http://localhost:8080, ative e execute a DAG elt_municipios_ibge

Prerequisitos: Git, Windows PowerShell 5.1 ou superior, Docker Desktop com Docker Compose v2, aproximadamente 8 GB de RAM livre e acesso de rede aos registries Docker, GitHub e PyPI durante a primeira construcao.


Componentes e Portas

Componente Imagem Porta Descricao
PostgreSQL postgres:16-alpine 127.0.0.1:5432 5 bancos: elt, bronze, silver, gold, airflow
Airflow Webserver apache/airflow:2.9.3-python3.11 127.0.0.1:8080 Interface de gerenciamento de DAGs
Airflow Scheduler apache/airflow:2.9.3-python3.11 - Execucao agendada de DAGs
MinIO API minio/minio:RELEASE.2024-09-22T00-33-43Z 127.0.0.1:9000 API S3-compativel
MinIO Console minio/minio:RELEASE.2024-09-22T00-33-43Z 127.0.0.1:9001 Interface web MinIO
JupyterLab jupyter/pyspark-notebook:python-3.11 127.0.0.1:8888 IDE interativo com 13 notebooks de dados
OpenMetadata docker.getcollate.io/openmetadata/server:2.0.2 127.0.0.1:8585 por padrao Catalogo, governanca, lineage e qualidade

Portas: Todas as portas sao publicadas apenas em 127.0.0.1 por seguranca. Atencao: Alterar para 0.0.0.0 expoe os servicos a rede local/externa. Ao fazer isso, garanta: (1) firewall com whitelist de IPs, (2) credenciais fortes, (3) TLS/proxy reverso na frente, e (4) redes Docker dedicadas.


O que e cada componente

Componente O que e Papel no projeto Onde e usado Licenca Links
Python 3.12 Linguagem de programacao interpretada Linguagem dos extractors, conectores e controller Todo o codigo-fonte do projeto PSF License python.org | License
PostgreSQL 16 Sistema de gerenciamento de banco relacional Banco para todas as camadas (bronze/silver/gold/elt/airflow) docker-compose.yml (servico postgres) PostgreSQL License postgresql.org | License
Apache Airflow 2.9.3 Orquestrador de workflows (DAGs) Executa, agenda e monitora pipelines ELT docker-compose.yml (servicos airflow-*) Apache 2.0 airflow.apache.org | License
Docker Plataforma de containerizacao Empacota servicos em containers isolados Infraestrutura base do lab Apache 2.0 docker.com | License
Docker Compose Orquestrador multi-container Define e gerencia todos os servicos com um comando docker-compose.yml Apache 2.0 docs.docker.com/compose | License
MinIO Object storage S3-compativel Datalake em formato Parquet (camada bronze/silver/gold) docker-compose.yml (servico minio), src/extractors/minio.py AGPL-3.0 min.io | License
MinIO SDK (minio-py) Cliente Python para API S3 do MinIO Upload/download de objetos Parquet no datalake src/connectors/minio_connector.py Apache 2.0 min.io/docs/minio/python | License
SQLAlchemy Toolkit ORM e SQL para Python Conexao com PostgreSQL/Oracle via pool de conexoes src/connectors/postgres_connector.py, src/connectors/oracle_connector.py MIT sqlalchemy.org | License
pandas Biblioteca de manipulacao de dados tabulares Leitura, transformacao e escrita de DataFrames src/extractors/*.py, src/models/ BSD-3-Clause pandas.pydata.org | License
PyArrow Implementacao Apache Arrow para Python Suporte a formato Parquet e vetores columnares src/extractors/s3.py (leitura parquet) Apache 2.0 arrow.apache.org/docs/python | License
OpenPyXL Leitura/escrita de arquivos Excel (.xlsx) Extracao de dados de planilhas Excel src/extractors/xlsx.py MIT openpyxl.readthedocs.io | License
Requests HTTP client para Python Chamadas a APIs REST e downloads de CSV src/extractors/api.py, src/extractors/s3.py, src/extractors/_security.py Apache 2.0 requests.readthedocs.io | License
psycopg2 Adaptador nativo PostgreSQL para Python Conexao direta com PostgreSQL via libpq src/connectors/postgres_connector.py LGPL-2.1+ ycopg.org | License
python-oracledb Driver Oracle para Python (modo Thin) Conexao com Oracle sem Oracle Client src/connectors/oracle_connector.py Apache 2.0 oracle.github.io/python-oracledb | License
google-api-python-client Cliente Python para Google APIs Acesso ao Google Sheets API v4 src/extractors/google_sheets.py Apache 2.0 github.com/googleapis/google-api-python-client | License
gspread Wrapper Python para Google Sheets Abstracao simplificada do Sheets API src/extractors/google_sheets.py MIT github.com/burnash/gspread | License
JupyterLab IDE interativo para notebooks Ambiente de exploracao e aprendizado de dados docker/Dockerfile.jupyter, data_lab/*.ipynb BSD-3-Clause jupyter.org | License
PySpark API Python para Apache Spark Processamento distribuido de dados (notebooks 10-12) docker/Dockerfile.jupyter (base image) Apache 2.0 spark.apache.org | License
NumPy Computacao numerica vetorial Arrays e operacoes matriciais (notebook 02) docker/Dockerfile.jupyter BSD-3-Clause numpy.org | License
Polars DataFrame framework em Rust Alternativa rapida ao Pandas (notebook 04) docker/Dockerfile.jupyter MIT pola.rs | License
DuckDB Database analitico embutido SQL sobre DataFrames (notebook 04) docker/Dockerfile.jupyter MIT duckdb.org | License
Matplotlib Visualizacao 2D para Python Graficos estaticos (notebook 08) docker/Dockerfile.jupyter PSF-based matplotlib.org | License
Seaborn Visualizacao estatistica Graficos de distribuicao, correlacao (notebook 08) docker/Dockerfile.jupyter BSD-3-Clause seaborn.pydata.org | License
Plotly Visualizacao interativa Dashboards e graficos interativos (notebook 08) docker/Dockerfile.jupyter MIT plotly.com | License
scikit-learn Machine Learning para Python Classificacao, regressao, pipelines (notebook 09) docker/Dockerfile.jupyter BSD-3-Clause scikit-learn.org | License
OpenMetadata Plataforma de catalogo e governanca Descoberta, glossario, ownership, lineage e qualidade docker-compose.yml Apache 2.0 open-metadata.org | License

Credenciais

As credenciais sao geradas automaticamente pelo .\setup.ps1 no arquivo .env.

Nunca commite o arquivo .env ao repositorio (protegido pelo .gitignore).

Servico Variavel no .env Como acessar
PostgreSQL POSTGRES_USER, POSTGRES_PASSWORD localhost:5432 com cliente SQL
Airflow AIRFLOW_ADMIN_USERNAME, AIRFLOW_ADMIN_PASSWORD http://localhost:8080
MinIO MINIO_ROOT_USER, MINIO_ROOT_PASSWORD http://localhost:9001
OpenMetadata OM_ADMIN_PASSWORD admin@open-metadata.org em http://localhost:8585

Para ver as credenciais, abra o arquivo .env na raiz do projeto.


Arquitetura

                    elt.global.schedule (tabela de controle)
                                  |
            +---------------------+----------------------+
            |                     |                      |
       load_bronze          load_silver            load_gold
       (extratores)      (transformacoes SQL)   (modelo dimensional)
            |                     |                      |
       GOOGLE SHEETS           DW query               DW query
       XLSX                    -> silver               -> gold
       S3 / CKAN / CSV_URL
       Oracle / PostgreSQL
       MinIO (parquet)
       API REST
       FTP

Camadas (Medallion Architecture)

Camada Descricao Destino
Bronze Extracao de dados brutos de fontes heterogeneas PostgreSQL bronze ou MinIO (parquet)
Silver Transformacao/limpeza via queries SQL PostgreSQL silver ou MinIO (parquet)
Gold Modelo dimensional (dimensoes e fatos) PostgreSQL gold ou MinIO (parquet)
Controle Tabela de schedule e log de execucoes PostgreSQL elt

Cada camada pode gravar em PostgreSQL (padrao) ou MinIO (parquet), basta configurar via config na tabela schedule.

Bancos de Dados

Banco Funcao Schema
elt Controle do framework global.schedule, global.controle_execucao
bronze Dados brutos (extracao) global.*
silver Dados transformados global.*
gold Modelo dimensional global.*
airflow Metadados do Airflow airflow_*

OpenMetadata

O OpenMetadata faz parte do mesmo docker-compose.yml e do projeto Docker elt. As credenciais sao geradas a partir do unico .env local; os servicos persistem somente os dados de autenticacao necessarios em seus bancos internos.

# Sobe ELT, Airflow, Jupyter e OpenMetadata em uma unica stack
.\setup.ps1

# Depois de executar a DAG elt_municipios_ibge, catalogue os ativos
.\scripts\openmetadata\manage.ps1 bootstrap

Acesse http://localhost:8585 (ou a porta definida em OPENMETADATA_PORT) com o usuario fixo admin@open-metadata.org e OM_ADMIN_PASSWORD do .env. A senha administrativa default do OpenMetadata e substituida automaticamente por uma senha aleatoria antes do setup concluir. O bootstrap pode ser repetido sem duplicar os objetos gerenciados e cria:

  • Services dos bancos elt, bronze, silver e gold e do Airflow
  • Dicionario de dados para o pipeline de municipios
  • Equipes e ownership demonstrativos
  • Glossario e classificacao de sensibilidade
  • Lineage de tabela e coluna entre Bronze, Silver e Gold
  • Testes de qualidade com resultados publicados no catalogo

Documentacao: politica de governanca e roteiro de demonstracao.

.\scripts\openmetadata\manage.ps1 status
.\scripts\openmetadata\manage.ps1 health
.\scripts\openmetadata\manage.ps1 stop

O setup completo requer aproximadamente 8 GB livres. Todos os containers e volumes sao agrupados no projeto Docker elt.

Upgrade da stack OpenMetadata anterior

A versao anterior desta branch usava o projeto Compose separado elt-openmetadata. O setup atual detecta containers desse projeto e para sem alterar seus volumes. Antes de atualizar, preserve o .env.openmetadata e faca backup dos volumes elt-openmetadata_openmetadata-postgres-data e elt-openmetadata_openmetadata-elasticsearch-data se precisar manter o catalogo antigo. Remova apenas os containers legados e execute setup.ps1; os volumes antigos permanecem intactos e o catalogo demonstrativo pode ser recriado com o bootstrap.

docker ps -a --filter "label=com.docker.compose.project=elt-openmetadata"
docker rm -f elt-openmetadata-server elt-openmetadata-migrate elt-openmetadata-elasticsearch elt-openmetadata-postgres
.\setup.ps1
.\scripts\openmetadata\manage.ps1 bootstrap

Nao use docker volume rm nesse fluxo sem ter confirmado o backup ou a perda intencional do catalogo anterior.


Commands Uteis

.\setup.ps1                # Subir tudo
.\setup.ps1 -Down          # Parar (volumes preservados)
.\setup.ps1 -PurgeVolumes  # Parar e apagar dados (pede confirmacao)
.\setup.ps1 -Status        # Ver status dos containers
.\setup.ps1 -Logs          # Ver logs (escolhe container)

Depois que setup.ps1 gerar e preencher o .env, a stack tambem pode ser iniciada manualmente:

docker compose up -d --build

Extratores Disponiveis

type_source Descricao Parametros principais
GOOGLE_SHEETS Google Sheets via API url, conexao_origem_id, table_source, header_row_source
XLSX Arquivo Excel local table_source, header_row_source
DW Query SQL em banco PostgreSQL database_source, schema_source, query_source
ORACLE Extracao de banco Oracle config.connection_airflow, schema_source, table_source
POSTGRE Extracao de banco PostgreSQL config.connection_airflow, schema_source, table_source
MINIO Arquivos Parquet/CSV do MinIO config.endpoint, config.bucket, config.object_name
FTP Download de arquivos via FTP config.ftp_host, config.ftp_base, config.file_pattern, config.file_format
S3 / CKAN / CSV_URL Download de CSV/Parquet via URL url, config.delimiter, config.encoding
API API REST generica config.connection_airflow, config.base_url, config.endpoint

Seguranca

  • Senhas geradas automaticamente com caracteres aleatorios criptograficos
  • Chave Fernet do Airflow gerada criptograficamente
  • Portas publicadas apenas em 127.0.0.1 (localhost)
  • Arquivos .env nao versionados (gitignore)
  • Credenciais nao expostas no terminal durante setup
  • Imagens Docker base fixadas por tag e digest SHA-256
  • Protecao contra path traversal em downloads
  • Protecao contra SSRF (validacao de esquema e resolucao DNS)
  • Limites de tamanho em downloads e extracao de ZIPs
  • Validacao de identificadores SQL em queries
  • Credenciais mascaradas em logs

Aplicacao em Producao

Este repositorio e projetado para desenvolvimento e testes locais. Para uso em producao:

  1. Secrets: Use Docker secrets, Vault, ou o gerenciamento de secrets do Airflow (nao arquivos .env)
  2. TLS: Configure TLS/proxy reverso para todas as portas expostas
  3. Network: Use redes Docker dedicadas; nunca exponha servicos diretamente
  4. Monitoring: Adicione Prometheus/Grafana para metricas de Airflow e PostgreSQL
  5. Backup: Configure backup automatico dos volumes elt_elt-pgdata e elt_elt-miniodata
  6. Logs: Centralize logs com ELK/Fluentd/Loki
  7. Resource Limits: Adicione deploy.resources.limits no docker-compose.yml

Estrutura do Projeto

elt/
+-- main.py                     # DAG Airflow (geracao dinamica)
+-- controller/                 # Orquestracao
|   +-- load_bronze.py
|   +-- load_silver.py
|   +-- load_gold.py
|   +-- dags.py                 # Notificacao por email
+-- models/
|   +-- bronze/extract.py       # Extrator generico
|   +-- silver/transform.py     # Transformacao generica
|   +-- gold/transform.py       # Modelo dimensional generico
+-- src/
|   +-- schedule/               # Leitura da tabela de controle
|   +-- connectors/             # Conectores de banco e servicos
|   |   +-- postgres_connector.py
|   |   +-- oracle_connector.py
|   |   +-- minio_connector.py
|   |   +-- airflow_connections.py
|   +-- extractors/             # Extratores registraveis
|   |   +-- base.py
|   |   +-- _security.py        # Utilitarios de seguranca
|   |   +-- google_sheets.py
|   |   +-- xlsx.py
|   |   +-- oracle.py
|   |   +-- postgres.py
|   |   +-- minio.py
|   |   +-- ftp.py
|   |   +-- s3.py
|   |   +-- api.py
|   +-- utils/
|   |   +-- validation.py       # Validacao de identificadores SQL
|   +-- historics/              # SCD Tipo 2
+-- sql/init/                   # Scripts de inicializacao do banco
+-- docker/
|   +-- Dockerfile.airflow
|   +-- airflow_init.sh
|   +-- requirements-airflow.txt
+-- docker-compose.yml
+-- .env                        # Credenciais (nao versionado)
+-- .env.example                # Template de configuracao
+-- data_lab/                   # JupyterLab notebooks (Data Lab)
|   +-- 00_...ipynb ate 12_...ipynb
|   +-- datasets/               # Datasets gerados pelos notebooks
+-- THIRD_PARTY_NOTICES.md      # Licencas de dependencias
+-- LICENSE                     # MIT License

Jupyter Data Lab

O ELT Lab inclui um ambiente JupyterLab com 13 notebooks para explorar e aprender conceitos de dados.

Como acessar

  1. O setup ja inicia o JupyterLab automaticamente
  2. Abra http://localhost:8888
  3. Na tela de login, insira a senha gerada no arquivo .env (JUPYTER_PASSWORD)
  4. O usuario e sempre jovyan (configurado via JUPYTER_USERNAME no .env)
  5. Navegue ate a pasta Data Lab no JupyterLab

Notebooks

# Notebook Conteudo
00 Boas Vindas e Validacao Verifica Python, Spark, PostgreSQL, todas as bibliotecas
01 Python para Dados Lists, dicts, comprehensions, funcoes, try/except, JSON
02 NumPy Arrays, indexacao, broadcasting, agregacoes
03 Pandas DataFrame, filtros, groupby, merge, NaN
04 Polars e DuckDB LazyFrame, SQL direto no DataFrame, performance
05 Arquivos CSV, Excel, Parquet, particionamento
06 APIs e JSON Mock server local, GET, erros, json_normalize
07 SQLAlchemy e PostgreSQL Conexao, DDL, DML, transacoes com cleanup
08 Visualizacao de Dados Matplotlib, Seaborn, Plotly (offline)
09 Scikit-Learn Basico Pipeline, train/test split, classification report
10 PySpark Fundamentos Schema, select, groupBy, join, window, explain
11 PySpark Parquet e Medalhao Bronze/Silver/Gold com PySpark + Parquet
12 Desafios de Entrevista Running total, gap-and-islands, deduplicacao, pivot

Stack do Data Lab

Biblioteca Versao Uso
NumPy 1.26.4 Arrays numericos
pandas 2.2.3 Manipulacao de DataFrames
Polars 1.12.0 DataFrame em Rust (rapido)
DuckDB 1.1.3 SQL analitico embutido
PyArrow 17.0.0 Formato Parquet
OpenPyXL 3.1.5 Leitura/escrita Excel
SQLAlchemy 2.0.36 Conexao com bancos
psycopg2 2.9.10 Adaptador PostgreSQL
Matplotlib 3.9.2 Graficos estaticos
Seaborn 0.13.2 Graficos estatisticos
Plotly 5.24.1 Graficos interativos
scikit-learn 1.5.2 Machine Learning
PySpark (base image) Processamento distribuido

Seguranca do Data Lab

  • Porta publicada apenas em 127.0.0.1 (localhost)
  • Autenticacao por senha (hash SHA-256, token desabilitado)
  • Tela de login obrigatoria no navegador (senha unica, sem token)
  • Todos os notebooks funcionam offline (sem internet)
  • Dados sinteticos (sem dados reais ou credenciais)
  • Diretorio ELT montado como somente leitura
  • Limites de recursos: 4GB RAM, 2 CPUs
  • Container nao roda como root
  • Imagem Docker com SHA-256 fixado (reprodutibilidade)

Como Usar

1. Tabela de schedule

A tabela elt.global.schedule e o coracao do framework. Cada linha define um step de extracao ou transformacao.

SELECT id, type_source, layer, projeto, table_destiny, schedule_cron
FROM elt.global.schedule
WHERE ativo = TRUE
ORDER BY projeto, layer, ordem;

2. Connections no Airflow

Connection ID Banco Descricao
elt_bronze bronze Extracao de dados
elt_silver silver Transformacao
elt_gold gold Modelo dimensional
elt_schedule elt Schedule + controle_execucao
google_sheets - Service account (se necessario)
minio - Credenciais MinIO (se utilizado)

3. Registrar novo projeto

Cada projeto precisa de ao menos um INSERT por camada (bronze, silver, gold):

-- Bronze: extracao de CSV
INSERT INTO elt.global.schedule
(type_source, layer, projeto, ordem, ativo,
 schedule_cron,
 url, table_source, table_destiny,
 schema_destiny, strategy_destiny,
 config)
VALUES
('CSV_URL', 'bronze', 'meu_projeto', 1, TRUE,
 '0 7 * * 5',
 'https://exemplo.com/dados.csv',
 'dados', 'minha_tabela',
 'global', 'truncate',
 '{"delimiter": ",", "encoding": "utf-8"}');

-- Silver: transformacao SQL
INSERT INTO elt.global.schedule
(type_source, layer, projeto, ordem, ativo,
 schedule_cron,
 database_source, schema_source,
 query_source,
 table_destiny, schema_destiny, strategy_destiny)
VALUES
('DW', 'silver', 'meu_projeto', 1, TRUE,
 '0 7 * * 5',
 'bronze', 'global',
 'SELECT * FROM global.minha_tabela WHERE coluna = valor',
 'minha_tabela_tratada', 'global', 'truncate');

-- Gold: modelo dimensional
INSERT INTO elt.global.schedule
(type_source, layer, projeto, ordem, ativo,
 schedule_cron,
 database_source, schema_source,
 query_source,
 table_destiny, schema_destiny, strategy_destiny)
VALUES
('DW', 'gold', 'meu_projeto', 1, TRUE,
 '0 7 * * 5',
 'silver', 'global',
 'SELECT categoria, COUNT(*) AS total FROM global.minha_tabela_tratada GROUP BY categoria',
 'dm_categoria', 'global', 'truncate');

Usando MinIO em vez de PostgreSQL

Para gravar uma camada como parquet no MinIO, adicione "minio" no config:

-- Bronze: gravar no MinIO
INSERT INTO elt.global.schedule
(type_source, layer, projeto, ordem, ativo,
 schedule_cron,
 url, table_destiny, schema_destiny, strategy_destiny,
 config)
VALUES
('CSV_URL', 'bronze', 'meu_projeto', 1, TRUE,
 '0 7 * * 5',
 'https://exemplo.com/dados.csv',
 'minha_tabela', 'global', 'truncate',
 '{"minio": {"bucket": "elt-datalake", "format": "parquet", "object_name": "bronze/minha_tabela.parquet"}}');

Fluxo flexivel por camada

Camada Origem Destino Config
Bronze Qualquer fonte PostgreSQL (padrao) Sem config
Bronze Qualquer fonte MinIO config.minio
Silver PostgreSQL (SQL) PostgreSQL (padrao) Sem config
Silver MinIO (parquet) PostgreSQL config.minio_source
Silver PostgreSQL MinIO config.minio
Gold PostgreSQL (SQL) PostgreSQL (padrao) Sem config
Gold MinIO (parquet) PostgreSQL config.minio_source
Gold PostgreSQL MinIO config.minio

4. DAGs geradas automaticamente

O Airflow cria automaticamente uma DAG para cada projeto com schedule_cron preenchido:

Projeto DAG gerada Schedule
municipios_ibge elt_municipios_ibge 0 4 * * 1 (segundas 04:00)

Alem disso, a DAG elt_pipeline (geral) executa todos os projetos.

5. Referencia de Cron

A coluna schedule_cron usa o formato padrao do Airflow:

minuto hora dia_do_mes mes dia_da_semana
Cron Significado
0 6 * * 1 Toda segunda-feira as 06:00
0 7 * * 1-5 Dias uteis (seg-sex) as 07:00
30 8 * * 1,3,5 Segunda, quarta e sexta as 08:30
0 9 1 * * Dia 1 de cada mes as 09:00
0 */2 * * * A cada 2 horas

Para testar expressoes cron: https://crontab.guru

Gerenciamento de Dependencias

  • Imagens Docker base: Fixadas com tag e digest SHA-256
  • Python (requirements-airflow.txt): Versoes sem upper bound, resolvidas via constraints oficiais
  • Airflow constraints: Dockerfile.airflow usa constraints oficiais da versao 2.9.3 (constraints-3.11.txt), garantindo compatibilidade entre providers e SDKs
  • Dependabot: Configurado em .github/dependabot.yml para monitorar atualizacoes semanais de pip e Docker
  • Security: src/extractors/_security.py fornece protecao contra path traversal, SSRF (validacao de esquema, IP, allowlist de hosts/CIDRs e redirects manuais com urljoin), e limites de download. DNS rebinding/TOCTOU e um risco residual documentado no modulo — para ambientes de alta seguranca, use firewall de egress, proxy ou allowlist de dominios

Pendencias registradas

  • pip-audit: Adicionar etapa pip-audit --desc ao pipeline CI para varredura periodica de vulnerabilidades nas dependencias Python
  • SBOM CycloneDX: Integrar geracao de SBOM (cyclonedx-py) no CI/CD para rastreabilidade completa de componentes de software

Licenca

MIT License - veja LICENSE para detalhes.

Dependencias de terceiros: veja THIRD_PARTY_NOTICES.md.

About

Laboratório de engenharia e governança de dados com pipelines orientados por metadados, Airflow, PostgreSQL, MinIO, Docker e OpenMetadata.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages