Docker PySpark
Ambiente em Docker para Engenheiros de Dados

#007 – Ambiente em Docker para Engenheiros de Dados


Introdução

Quer um ambiente pronto para codar? Bom, hoje trago um ambiente todo em Docker com PySpark, Python3, Jupyter Notebook e um banco de dados relacional, neste caso Postgres, para os devs de plantão, onde o uso do Docker tem se tornado cada vez mais popular entre engenheiros de dados, desenvolvedores e áreas correlatas, por sua capacidade de criar ambientes portáteis e consistentes.

Além disso, o Docker oferece isolamento entre os serviços que você está executando, o que aumenta a segurança e a confiabilidade das suas aplicações. Cada contêiner é isolado e não interfere nos outros, permitindo que você execute diferentes versões da mesma aplicação ou diferentes serviços no mesmo servidor de forma segura.

Para rodar esse ambiente na sua máquina, você irá precisar do Docker e de uma IDE de sua preferência, por exemplo o VS Code ou o Trae.


1. Dockerfile

O Dockerfile é um arquivo de texto que contém todas as instruções necessárias para criar uma imagem Docker. Ele define o que a imagem deve conter e como deve ser configurada. Por exemplo, no nosso caso, estamos especificando que a imagem deve ser baseada em Python 3.10 e que deve incluir o Java OpenJDK 11, além de instalar todas as dependências necessárias para o funcionamento do PySpark. O Dockerfile é essencial para automatizar o processo de construção de imagens, garantindo que você sempre tenha um ambiente consistente.

    
    FROM python:3.10-bullseye
    

# Atualiza os repositórios e instala o Java (OpenJDK 11) RUN apt-get update && \ apt-get install -y openjdk-11-jre && \ rm -rf /var/lib/apt/lists/*

# Define JAVA_HOME ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 ENV PATH="$JAVA_HOME/bin:$PATH"

# Cria e ativa o ambiente virtual ENV VIRTUAL_ENV=/opt/venv RUN python -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH"

# Copia os arquivos de requirements COPY requirements.txt .

# Instala as dependências Python dentro da venv RUN pip install --upgrade pip && pip install -r requirements.txt

# Define o diretório de trabalho WORKDIR /app

# Copia o código da aplicação COPY . .

CMD ["jupyter", "notebook", "--ip=0.0.0.0", "--port=8888", "--allow-root", "--no-browser", "--NotebookApp.token=''"]

2. requirements.txt

Esse arquivo diz as bibliotecas que o Python irá baixar. Nesse caso, são os itens acima. É importante ressaltar que, ao utilizar bibliotecas bem definidas no arquivo requirements.txt, você garante que todas as versões de bibliotecas necessárias para o seu projeto estão documentadas, evitando problemas de compatibilidade no futuro. Além disso, você pode adicionar novas bibliotecas que achar necessárias conforme o projeto evolui, facilitando o gerenciamento de dependências.

    
    pyspark
    psycopg2-binary
    pandas
    notebook
    
    

3. docker-compose.yml

O arquivo docker-compose.yml é fundamental quando você precisa trabalhar com múltiplos serviços que interagem entre si. Neste caso, estamos criando dois contêineres: um para o aplicativo em PySpark e outro para o banco de dados PostgreSQL. O uso do Docker Compose simplifica a configuração e o gerenciamento de serviços interdependentes, permitindo que você defina todos os parâmetros necessários em um único arquivo. Isso torna o processo de inicialização de ambientes complexos muito mais simples e rápido.

    
    version: '3.8'
    

services: spark: build: . container_name: pyspark_app volumes: - .:/app environment: - PYSPARK_PYTHON=python - JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 - POSTGRES_HOST=postgres - POSTGRES_DB=postgres - POSTGRES_USER=adm - POSTGRES_PASSWORD=adm depends_on: - postgres ports: - "8888:8888" # Exemplo: Jupyter notebook, se quiser rodar

postgres: image: postgres:14 container_name: postgres_db environment: - POSTGRES_DB=postgres - POSTGRES_USER=adm - POSTGRES_PASSWORD=adm ports: - "5432:5432" volumes: - pgdata:/var/lib/postgresql/data

volumes: pgdata:

4. Hora de Rodar

Com essas configurações feitas, basta rodar o comando docker-compose up –build. Esse comando irá demorar alguns minutos para baixar todas as dependências e construir as imagens. É importante ter paciência durante esse processo, pois uma vez que tudo estiver configurado corretamente, sua aplicação estará pronta para uso. Além disso, sempre que você fizer alterações no Dockerfile ou no docker-compose.yml, você deve rodar o comando novamente para que as alterações sejam aplicadas.

Após isso, abra este LINK. Isso abrirá o Jupyter Notebook pronto para você começar a codar. O Jupyter Notebook é uma ferramenta poderosa para trabalhar com dados, permitindo que você escreva código, visualize resultados e documente seu trabalho em um único lugar. É ideal para protótipos rápidos e experimentação com dados.

É importante se familiarizar com a interface do Jupyter, pois ela oferece diversas funcionalidades que podem facilitar seu trabalho. Por exemplo, você pode usar células de código para executar comandos em Python e células de markdown para documentar suas análises, tornando seu trabalho mais organizado e compreensível para outros.

Veja como você deve ver o Jupyter Notebook ao abrir o link:

Docker-JupyterNotebook

Para fazer o primeiro teste, isto é, fazer a conexão com o banco Postgres e ver se está realmente funcionando, basta adicionar um arquivo main.ipynb como descrito abaixo. Este arquivo servirá como o ponto de partida para suas análises e testes iniciais. Além de verificar a conexão, você poderá realizar consultas e manipulações de dados diretamente do Jupyter Notebook.

CMD 1

    
    from pyspark.sql import SparkSession
    

spark = SparkSession.builder \ .appName("PySparkPostgres") \ .config("spark.jars.packages", "org.postgresql:postgresql:42.3.1") \ .getOrCreate()

df = spark.read \ .format("jdbc") \ .option("url", "jdbc:postgresql://postgres:5432/postgres") \ .option("dbtable", "funcionarios.app_test") \ .option("user", "adm") \ .option("password", "adm") \ .option("driver", "org.postgresql.Driver") \ .load()

df.show()

CMD 2

    
    df.createOrReplaceTempView("app_test")
    

procurar_nome = spark.sql("SELECT NOME FROM app_test WHERE NOME = 'Marllon' ") procurar_nome.show()

Docker-JupyterNotebook-2

O código acima conecta o PySpark ao banco de dados PostgreSQL usando JDBC. Ele cria uma sessão do Spark e lê dados de uma tabela específica no banco. É essencial que o driver JDBC correto esteja configurado para garantir que a conexão funcione corretamente. Uma vez conectado, você pode realizar operações de leitura e escrita no banco de dados através do PySpark ou SparkSQL, explorando grandes volumes de dados de forma eficiente.

É essencial ajustar as credenciais e os nomes das tabelas conforme o seu ambiente e para proteger a segurança dos dados. Recomenda-se explorar recursos avançados do PostgreSQL, como a criação de índices e visualizações, para melhorar o desempenho das consultas. Lembre-se de que a senha, o usuário e a tabela atualmente estão definidos como adm (senha e usuário), e o esquema + tabela como funcionarios.app_test. Embora tenha seguido esse padrão, é possível conectar-se ao banco de dados por meio de plataformas como o DBevear, criar a tabela dentro do mesmo (se não souber como, veja o arquivo main_postgres.sql dentro do repositório desse projeto no meu GitHub) e, em seguida, realizar a consulta no Jupyter Notebook.


Conclusão

Faça um clone do meu projeto, faça na sua máquina o passo a passo e me conte aqui nos comentários se deu tudo certo com você também. Feedbacks são sempre bem-vindos e ajudam a comunidade a crescer. Além disso, sinta-se à vontade para compartilhar suas experiências e dúvidas, pois isso pode enriquecer a discussão e ajudar outros leitores a superar os desafios que você enfrentou.

O link desses arquivos, e também os comandos SQL para criar a tabela, inserir dados, etc, se encontram no meu GitHub

Confira também nosso artigo sobre Tkinter!

Compartilhe:

Apaixonado por dados e tecnologias transformadoras, com 4+ anos de experiência na interseção entre engenharia de dados e inovação. Atualmente, como Engenheiro de Dados Sênior, me dedico à criação de ecossistemas de dados escaláveis, aplicando sua expertise no dinâmico setor de crédito. Ao longo da sua trajetória, projetou inúmeros pipelines de dados robustos para plataformas que atendiam milhares de usuários, bem como sistemas legados, integrando-os às soluções nativas da nuvem (AWS/Azure) por meio de frameworks ETL/ELT escaláveis.