🐳 ATIVIDADE 17: CONTAINERIZAÇÃO DE AMBIENTES COM DOCKER
Para realizar este laboratório com sucesso, certifique-se de ter compreendido os conceitos apresentados no:
👉 CAPÍTULO 17: ESTRATÉGIAS DE TESTE e CAPÍTULO 04 DE BANCO DE DADOS: SETUP COMPLETO
Bem-vindo a mais uma etapa prática da sua jornada na Engenharia de Software! Após automatizarmos nossos testes no pipeline de CI/CD, agora resolveremos um dos problemas mais clássicos e irritantes no desenvolvimento de software: "Na minha máquina funciona, por que não funciona no servidor de produção?" 🤦♂️💻
Hoje, aprenderemos sobre Docker e Docker Compose, as tecnologias líderes de mercado que revolucionaram a forma de empacotar, distribuir e rodar aplicações em ambientes isolados e idênticos, garantindo previsibilidade absoluta! 🚀
🎯 Objetivos de Aprendizagem do Laboratório
Ao final deste laboratório prático (estimativa: 4 horas presenciais / autoguiadas), você será capaz de:
- Compreender os conceitos fundamentais de Contêineres vs Máquinas Virtuais.
- Escrever um Dockerfile otimizado para empacotar uma aplicação web Python 3.11+ com Flask 3.x.
- Criar um arquivo docker-compose.yml para orquestrar múltiplos contêineres (App Flask + PostgreSQL 17) em rede local isolada.
- Gerenciar redes virtuais privadas e volumes persistentes no ambiente Docker.
🏢 O Cenário Prático (Seu Desafio)
Na TecProExpress, a equipe de desenvolvimento estava enfrentando um caos diário de configuração. Cada desenvolvedor usava uma versão diferente do Python, um usava SQLite local, outro usava PostgreSQL nativo do Windows na porta 5432, e um terceiro usava uma versão desatualizada de dependências que quebrava as migrações. A integração de novos programadores demorava até 3 dias apenas para configurar o ambiente local!
"Seu desafio como Arquiteto de Soluções é padronizar e automatizar 100% do ambiente da TecProExpress. Você criará o arquivo
Dockerfileda aplicação web (Python 3.11, Flask 3.x e SQLAlchemy 2.0) e um arquivodocker-compose.ymlque sobe, com um único comando, o servidor da aplicação e o banco de dados PostgreSQL 17 configurados para conversar entre si em uma rede virtual isolada."
🧠 Fundamentos: A Teoria Traduzida
- Imagem Docker: É um pacote imutável e somente-leitura que contém tudo o que é necessário para rodar a aplicação (código, dependências do
requirements.txt, runtime do Python, variáveis de ambiente e arquivos). - Contêiner Docker: É a instância em execução de uma imagem. Ele compartilha o kernel do sistema operacional do host, tornando-o extremamente leve, rápido e com consumo mínimo de memória.
- Dockerfile: O script com comandos sequenciais para construir a Imagem do contêiner.
- Docker Compose: A ferramenta que permite definir e rodar aplicações multi-contêiner. Com um único comando (
docker compose up), todas as dependências (banco relacional, cache, app web) sobem prontas.
📊 Arquitetura do Ambiente Orquestrado com Docker
flowchart TD
subgraph Host ["Máquina do Desenvolvedor (Host OS)"]
direction TB
subgraph DockerNet ["Rede Virtual Isolada (tecpro-network)"]
direction LR
App["Contêiner Web: Flask 3.x + SQLAlchemy 2.0"] <-->|Porta Interna 5432| DB[("Contêiner Database: PostgreSQL 17")]
end
PortApp["Porta Física Exposta: 5000"] <-->|Direciona Requisições HTTP| App
end
subgraph Persistencia ["Armazenamento Externo"]
Volume[("Volume Docker: pgdata")] <---> DB
end
style Host fill:#f5f7fa,stroke:#333,stroke-width:2px
style DockerNet fill:#e1f5fe,stroke:#0288d1,stroke-width:2px
style Persistencia fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
style App fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
style DB fill:#ffe0b2,stroke:#f57c00,stroke-width:2px
📖 Exemplo Guiado: Dockerização de Ponta a Ponta
Para empacotarmos a aplicação Flask 3.x da TecProExpress integrada ao PostgreSQL, utilizaremos a estratégia recomendada de infraestrutura como código.
1. 🛠️ O Arquivo Dockerfile da Aplicação
Criamos um arquivo com o nome exato Dockerfile (sem extensão) na raiz do projeto para definir a construção da imagem leve:
# Imagem base oficial leve do Python 3.11
FROM python:3.11-slim
# Evita a geração de arquivos .pyc e força flush imediato de logs
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
WORKDIR /app
# Copia dependências e instala sem cache para manter a imagem enxuta
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copia código-fonte da aplicação
COPY . .
# Expõe a porta padrão do Flask
EXPOSE 5000
# Comando para iniciar o servidor web
CMD ["python", "main.py"]
2. 📄 O Arquivo docker-compose.yml de Orquestração
Na mesma raiz do projeto, criamos o arquivo docker-compose.yml para conectar a nossa aplicação ao banco de dados PostgreSQL de forma indestrutível:
services:
# Serviço 1: Banco de Dados PostgreSQL 17
database:
image: postgres:17-alpine
container_name: tecpro-db
restart: always
environment:
POSTGRES_DB: tecproexpress
POSTGRES_USER: tecpro_admin
POSTGRES_PASSWORD: SenhaSuperSegura123
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- tecpro-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U tecpro_admin -d tecproexpress"]
interval: 5s
timeout: 5s
retries: 5
# Serviço 2: Aplicação Web Flask 3.x
web-app:
build: .
container_name: tecpro-web-app
restart: always
ports:
- "5000:5000"
environment:
- DATABASE_URL=postgresql+psycopg2://tecpro_admin:SenhaSuperSegura123@database:5432/tecproexpress
depends_on:
database:
condition: service_healthy
networks:
- tecpro-network
# Definição dos Recursos Compartilhados
volumes:
pgdata:
driver: local
networks:
tecpro-network:
driver: bridge
💻 Execução do Docker Compose & Logs no Terminal
Para subir todo o ecossistema (Aplicação Web + Banco de Dados PostgreSQL) com um único comando:
# Subir os contêineres e compilar a imagem em segundo plano
docker compose up -d --build
# Inspecionar o status dos serviços em execução
docker compose ps
🖥️ Saída Esperada no Terminal:
[+] Building 3.2s (8/8) FINISHED
[+] Running 3/3
✔ Network tecpro-network Created 0.1s
✔ Container tecpro-db Started 0.4s
✔ Container tecpro-web-app Started 0.8s
NAME IMAGE COMMAND SERVICE STATUS PORTS
tecpro-db postgres:17-alpine "docker-entrypoint.s…" database running 0.0.0.0:5432->5432/tcp
tecpro-web-app tecproexpress-web-app "python main.py" web-app running 0.0.0.0:5000->5000/tcp
🛠️ Prática Obrigatória 1: Desenho da Rede de Contêineres
Cenário: Mapeamento conceitual do ecossistema de contêineres e fluxo de comunicação.
- Desenhe um diagrama
flowchartno Mermaid representando a arquitetura dos contêineres da sua aplicação. - Destaque as portas físicas do Host (computador físico) expostas e como elas se mapeiam para as portas internas dos contêineres do Docker.
- Evidencie a comunicação interna entre a aplicação e o banco PostgreSQL utilizando a rede virtualizada privada.
🏁 Resultado Esperado (Para sua Referência)
Um diagrama visual nítido exibindo o redirecionamento de portas (port-forwarding), volumes de persistência e a barreira da rede virtual.
🛠️ Prática Obrigatória 2: Criando os Arquivos de Configuração
Cenário: Escrevendo os scripts de containerização para o seu projeto semestral.
- Escreva o script
Dockerfilepersonalizado para o seu sistema de grupo, adaptando caso seu ecossistema necessite de variáveis ou passos específicos. - Escreva o arquivo
docker-compose.ymlque orquestra a aplicação de vocês integrada com um banco de dados persistido e mapeamento de portas do host para o contêiner.
📤 Instruções de Entrega (Microsoft Teams)
Após projetar a sua infraestrutura containerizada:
- Salve o arquivo de especificações e códigos com o nome
Atividade_17.mdna pastaes-atv-17-conteineres-docker/do seu repositório GitHub. - Certifique-se de fazer o commit e push para o repositório público.
- Submeta o link do seu repositório no Microsoft Teams para avaliação do professor.
💡 Checkpoint de Lógica
Reflexão Profissional:
No arquivo docker-compose.yml, a URL de conexão do banco de dados na aplicação web foi definida como postgresql+psycopg2://tecpro_admin:SenhaSuperSegura123@database:5432/tecproexpress em vez de localhost:5432. Por que a palavra database funciona ali dentro do Docker? E o que aconteceria com os dados do banco de dados do PostgreSQL quando o contêiner fosse deletado e recriado, considerando que usamos a seção volumes?
Respostas Técnicas:
- O Docker possui um servidor DNS interno embutido em suas redes do tipo
bridgeque resolve automaticamente o nome do serviço do Compose — no caso,database— diretamente para o endereço IP virtual interno do contêiner do Postgres. - Graças à declaração do volume
pgdatamapeado para o diretório/var/lib/postgresql/data, os dados bancários permanecem armazenados de forma persistente no sistema hospedeiro, não se perdendo mesmo quando o contêiner é totalmente destruído e recriado comdocker compose down. 🐳💾🧠
📊 Rubrica Formativa de Avaliação
| Critério de Avaliação | Insuficiente (0% - 40%) | Regular (41% - 70%) | Excelente (71% - 100%) |
|---|---|---|---|
| Containerização com Dockerfile | Dockerfile com sintaxe incorreta ou gerando imagens pesadas sem isolamento. | Escreve o Dockerfile mas esquece flags de otimização (`--no-cache-dir`, variáveis de ambiente). | Dockerfile impecável utilizando `python:3.11-slim`, variáveis `PYTHONDONTWRITEBYTECODE=1` e sem acúmulo de cache no pip. |
| Orquestração Multi-serviço (Docker Compose) | Erros na sintaxe YAML do `docker-compose.yml` ou ausência de mapeamento de portas e volumes. | Orquestra a aplicação e o banco mas esquece da persistência em `volumes`. | Compose perfeito com serviços orquestrados (`depends_on` com `healthcheck`), DNS do Docker e volume persistente `pgdata`. |
| Entrega no GitHub | Entrega fora da pasta `es-atv-17-conteineres-docker/`. | Arquivo entregue sem a explicação da rede virtual do Compose. | Submete `Atividade_17.md` contendo Dockerfile, Compose YAML e diagrama Mermaid de portas/redes formatados. |