Do Zero à API: Um Guia Prático com FastAPI, Docker e PostgreSQL
Do Zero ao Docker: Como Criei um Ambiente de Desenvolvimento Back-end Completo com FastAPI e PostgreSQL Passo a Passo
Comecei do zero para montar um ambiente completo de desenvolvimento back-end usando FastAPI e PostgreSQL, tudo dentro de contêineres Docker. Aprendi como criar um sistema que facilita o desenvolvimento, garante consistência e pode ser facilmente levado para produção.
Nesse processo, organizei toda a estrutura do projeto pensando na integração entre a API e o banco de dados, além de configurar o Docker para rodar tudo de forma automática e eficiente. Isso me permitiu trabalhar de maneira mais rápida e segura, evitando problemas comuns com ambientes diferentes.
Se você quer entender como juntar essas tecnologias para ter uma base sólida de desenvolvimento, este artigo explica passo a passo o que fiz para criar um ambiente funcional e prático, mesmo começando do zero.
Principais Conclusões:
- O ambiente criado facilita o desenvolvimento e a integração entre FastAPI e PostgreSQL.
- O uso do Docker garante que o sistema rode igual em qualquer máquina.
- A configuração permite testes rápidos e manutenção simplificada do projeto.
Visão Geral do Projeto Back-end
Neste projeto, criei um ambiente que integra um servidor rápido e eficiente com um banco de dados robusto. A ideia é ter todas as ferramentas necessárias para desenvolver, testar e rodar uma aplicação back-end de forma simples e organizada.
Objetivo do Ambiente de Desenvolvimento
Meu principal objetivo foi montar um ambiente que fosse fácil de configurar e que permitisse o desenvolvimento ágil. Queria evitar problemas comuns com instalações locais, assim o ambiente deveria ser replicável em qualquer máquina.
Busquei criar um sistema onde o FastAPI, que é rápido e moderno, comunicaria diretamente com o PostgreSQL, banco de dados conhecido pela sua segurança e performance.
Também precisava que tudo fosse encapsulado em containers Docker. Isso evita conflitos de versões e facilita o compartilhamento do ambiente com outros desenvolvedores.
Tecnologias Utilizadas
Optei pelo FastAPI por sua simplicidade e alta performance, além de suportar async, o que melhora a resposta da API.
Usei o PostgreSQL como banco de dados, pela sua estabilidade e recursos avançados, como suporte a JSON e consultas complexas.
O Docker é a base para o ambiente. Com ele, pude criar containers para o FastAPI e para o PostgreSQL, rodando isoladamente mas conectados.
Também utilizei o Docker Compose para orquestrar os containers, assim posso iniciar todo o ambiente com um único comando.
Além disso, configurei volumes Docker para garantir que os dados do banco persistam mesmo se o container for parado ou reiniciado.
O que é Docker e Por Que Utilizar
Docker é uma ferramenta que facilita a criação, envio e execução de aplicativos dentro de containers. Isso ajuda a manter o ambiente de desenvolvimento sempre igual, evitando problemas causados por diferenças entre máquinas.
Com Docker, o processo para configurar aplicações fica mais rápido e menos sujeito a erros. Também permite que várias partes do sistema rodem de forma isolada e segura.
Benefícios do Docker para Desenvolvedores
Para mim, a maior vantagem do Docker é a portabilidade. Posso criar um ambiente com FastAPI e PostgreSQL na minha máquina e garantir que ele vá funcionar igual em qualquer outro lugar, como um servidor ou computador de outro time.
Outra coisa importante é o isolamento. Cada serviço roda em seu próprio container, assim não há conflito entre versões de bibliotecas ou bancos de dados diferentes.
Além disso, Docker facilita o trabalho em equipe, porque todos usam o mesmo ambiente, o que evita dores de cabeça com "funciona na minha máquina".
Componentes Essenciais do Docker
Docker é formado por três partes principais: o Docker Engine, as imagens e os containers.
O Docker Engine é o programa que roda no sistema e cria ou gerencia containers. Ele usa imagens, que são como modelos prontos do ambiente, para gerar esses containers.
Containers são ambientes isolados e leves que executam as aplicações. Eles iniciam rápido e consomem poucos recursos, diferente de máquinas virtuais.
Esses componentes juntos tornam o desenvolvimento e a implantação mais simples e eficiente, permitindo criar ambientes complexos usando comandos simples.
Preparando o Ambiente Local
Antes de criar o ambiente de desenvolvimento, é essencial garantir que as ferramentas necessárias estejam instaladas e que as configurações básicas estejam ajustadas. Isso facilita o uso do Docker para rodar o FastAPI e o PostgreSQL sem problemas.
Instalando Docker e Docker Compose
Para começar, instale o Docker no seu computador. Use o site oficial do Docker (docker.com) para baixar a versão compatível com seu sistema operacional (Windows, Mac ou Linux).
Após instalar o Docker, verifique se ele está funcionando abrindo o terminal e executando:
docker --version
Também é importante instalar o Docker Compose, que ajuda a orquestrar os containers. Em muitas versões do Docker, o Compose já vem junto. Para checar, rode:
docker-compose --version
Se não estiver instalado, siga as instruções no site oficial do Docker Compose para instalar separadamente.
Configurando Variáveis de Ambiente
Para evitar expor dados sensíveis no código, criei um arquivo .env
. Nele ficam as variáveis de ambiente, como usuário, senha e nome do banco de dados.
Exemplo básico do .env
:
POSTGRES_USER=meu_usuario
POSTGRES_PASSWORD=minha_senha
POSTGRES_DB=meu_banco
Esse arquivo deve estar no mesmo diretório do docker-compose.yml
. O Docker Compose vai ler essas variáveis para configurar o container do PostgreSQL automaticamente.
Assim, manter as senhas e dados fora do código facilita a segurança e a manutenção do projeto.
Estruturando o Projeto com FastAPI
Para organizar meu projeto, precisei definir uma estrutura clara de pastas, configurar o FastAPI corretamente e gerenciar as dependências. Esses passos foram fundamentais para manter o código limpo e facilitar a expansão no futuro.
Criando a Estrutura de Pastas
Comecei dividindo o projeto em pastas específicas para cada função. Usei uma pasta chamada app
para colocar o código principal, como rotas, modelos e serviços.
Dentro de app
, criei subpastas para:
- routers (definição das rotas da API)
- models (modelos do banco de dados)
- schemas (validação dos dados com Pydantic)
- core (configurações e utilitários)
Também mantive arquivos como main.py
na raiz da pasta app
para iniciar o servidor. Essa organização facilita encontrar e modificar partes específicas do código.
Configuração Inicial do FastAPI
No arquivo main.py
, comecei importando o FastAPI e criando a instância da aplicação. Isso é básico, mas preciso para rodar o servidor.
Depois, adicionei middleware para lidar com CORS, o que permite que o frontend acesse a API sem problemas.
Também configurei um roteador básico para testar as rotas. Assim, posso garantir que minha API está funcionando antes de adicionar funcionalidades mais complexas.
Gerenciamento de Dependências com Poetry
Usei o Poetry para gerenciar pacotes e dependências. Ele facilita criar um ambiente virtual e manter o arquivo pyproject.toml
atualizado.
Para começar, executei poetry init
para criar o projeto e adicionei FastAPI, Uvicorn e outras bibliotecas com poetry add
.
Com o Poetry, qualquer desenvolvedor pode clonar meu projeto e rodar poetry install
, instalando tudo automaticamente. Isso evita conflitos de versões e mantém o ambiente consistente.
Configurando o Banco de Dados PostgreSQL
Para que o ambiente de desenvolvimento funcione bem, é essencial preparar o serviço do banco de dados corretamente. Além disso, garantir que os usuários e permissões estejam configurados evita erros de acesso e problemas de segurança.
Criando e Inicializando o Serviço PostgreSQL no Docker
Eu comecei criando um container Docker para o PostgreSQL usando a imagem oficial. No arquivo docker-compose.yml
, defini o serviço com as variáveis de ambiente necessárias, como POSTGRES_USER
, POSTGRES_PASSWORD
e POSTGRES_DB
.
services:
db:
image: postgres:15
environment:
POSTGRES_USER: meu_usuario
POSTGRES_PASSWORD: minha_senha_segura
POSTGRES_DB: meu_banco
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
A linha de volumes mantém os dados persistentes mesmo se o container for reiniciado ou removido. Isso é importante para não perder informações durante o desenvolvimento.
Usei o comando docker-compose up -d
para iniciar o serviço em segundo plano, o que permitiu usar o banco logo em seguida.
Gerenciamento de Usuários e Permissões
Depois que o PostgreSQL estava rodando, criei usuários específicos para o meu projeto. Isso ajuda a controlar quem pode acessar o banco e que tipo de ação pode fazer.
Usei comandos SQL simples para criar e editar permissões, geralmente pelo cliente psql
dentro do container:
- Criar usuário:
CREATE USER desenvolvedor WITH PASSWORD 'senha_forte';
- Dar permissões ao banco:
GRANT ALL PRIVILEGES ON DATABASE meu_banco TO desenvolvedor;
Criei um usuário apenas com permissões para leitura em outro banco para testar segurança. Sempre restrinjo o acesso para limitar riscos e evitar erros em produção.
Mantive a regra de conceder somente as permissões necessárias. Isso facilita o controle e mantém o ambiente mais seguro durante o desenvolvimento.
Dockerizando o FastAPI
Para criar um ambiente de desenvolvimento com FastAPI, é preciso construir uma imagem Docker que contenha todas as dependências do projeto. Também é essencial configurar comandos de entrada para que o container rode o servidor corretamente sempre que for inicializado.
Criando o Dockerfile para FastAPI
No Dockerfile, comecei escolhendo a imagem base oficial do Python, que já traz o ambiente necessário para rodar o FastAPI. Depois, copiei os arquivos do projeto e instalei as dependências listadas no requirements.txt
usando o pip
.
Usei um arquivo Dockerfile simples assim:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
Essa estrutura garante que as dependências estejam instaladas antes de copiar o código, otimizando o cache durante o build.
Gerenciando Entrypoints e Comandos
Para o container iniciar o FastAPI, configurei o comando padrão para rodar o Uvicorn, que é o servidor ASGI recomendado. Isso é feito usando a instrução CMD
no Dockerfile.
O comando que usei foi:
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Isso permite que o FastAPI fique disponível externamente na porta 8000. Evito usar ENTRYPOINT
para flexibilizar comandos de override, mas poderia usar para comandos fixos.
Também defino a opção --host
para aceitar conexões externas, pois o padrão só permite localhost. Essa configuração é crucial para o ambiente Docker funcionar corretamente.
Orquestrando Serviços com Docker Compose
Para criar um ambiente de desenvolvimento organizado, usei o Docker Compose para gerenciar os serviços do FastAPI e PostgreSQL. Ele simplifica a execução de múltiplos contêineres ao mesmo tempo, garantindo que cada serviço se comunique de forma eficiente.
Configurando o docker-compose.yml
No arquivo docker-compose.yml, defini dois serviços principais: web para a aplicação FastAPI e db para o banco PostgreSQL. Usei imagens oficiais para o PostgreSQL e construí a imagem da API a partir do Dockerfile local.
Aqui está um exemplo básico:
services:
web:
build: .
ports:
- "8000:8000"
depends_on:
- db
db:
image: postgres:13
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydatabase
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Incluí variáveis de ambiente para configurar o banco e volume para persistir dados. O depends_on garante que o banco inicie antes da API.
Rede entre Contêineres
Para a comunicação entre os serviços, o Docker Compose cria uma rede interna automaticamente. Isso permite que os contêineres se comuniquem usando os nomes dos serviços como host.
Na configuração, a aplicação FastAPI acessa o PostgreSQL usando o host db, o nome do serviço do banco definido no Compose.
Isso evita expor o banco diretamente na rede externa e mantém o ambiente seguro e organizado.
Se precisar de conexões externas, basta mapear as portas desejadas no serviço correspondente.
Migrations e Gerenciamento de Base de Dados
Neste projeto, organizei o controle da estrutura do banco de dados e a criação de dados iniciais para facilitar o desenvolvimento e a manutenção. A ferramenta escolhida para gerenciar as mudanças no banco é o Alembic, enquanto scripts específicos cuidam dos dados que precisam existir desde o início.
Utilizando Alembic para Migrations
Eu usei o Alembic para criar e gerenciar migrations no PostgreSQL. Ele permite gerar arquivos que representam mudanças na estrutura do banco, como tabelas novas ou colunas adicionadas. Cada vez que altero o modelo do FastAPI, crio uma migration para manter o banco sincronizado.
Para iniciar, configurei o Alembic com o arquivo alembic.ini
e o diretório versions
. Uso comandos como alembic revision --autogenerate -m "descrição"
para criar as migrations. Depois, aplico com alembic upgrade head
.
Assim, evito erros manualmente alterando o banco e posso controlar o histórico das mudanças. Essas práticas garantem que o ambiente de desenvolvimento seja sempre atualizado.
Scripts de Inicialização de Dados
Além da estrutura do banco, precisei popular dados iniciais, como usuários admin e configurações básicas. Criei scripts Python que rodam após a inicialização do banco para inserir esses dados.
Organizei esses scripts dentro de uma pasta específica no projeto. Eles verificam se os dados já existem antes de inserir para evitar duplicação. Também uso variáveis de ambiente para definir informações sensíveis como senhas.
Essa abordagem permite que qualquer novo ambiente gere os dados básicos automaticamente, economizando tempo e evitando falhas manuais. Ela é importante para manter os dados consistentes e prontos para o uso do sistema.
Integração FastAPI e PostgreSQL
Para criar um ambiente funcional, precisei garantir uma conexão estável entre FastAPI e PostgreSQL. Também tive que manipular dados de forma eficiente usando SQLModel, que facilita o trabalho com banco de dados no Python.
Configurando Conexão com SQLModel
Comecei instalando o SQLModel, que combina Pydantic e SQLAlchemy para facilitar a conexão com o banco.
Configurei a URL da base de dados com o padrão:
SQLALCHEMY_DATABASE_URL = "postgresql://usuario:senha@localhost/nome_do_banco"
Depois, criei o engine de conexão:
from sqlmodel import create_engine
engine = create_engine(SQLALCHEMY_DATABASE_URL, echo=True)
O echo=True ajuda a ver os comandos SQL no console, útil para debug.
Para garantir que as tabelas fossem criadas automaticamente, usei:
from sqlmodel import SQLModel
SQLModel.metadata.create_all(engine)
Assim, minha aplicação já fica pronta para operar com o banco.
Manipulação de Dados com ORM
Uso o SQLModel para definir minhas classes modelo que representam tabelas.
Por exemplo:
from sqlmodel import SQLModel, Field
class Usuario(SQLModel, table=True):
id: int = Field(default=None, primary_key=True)
nome: str
email: str
Para inserções, abro uma sessão:
from sqlmodel import Session
with Session(engine) as session:
usuario = Usuario(nome="Ana", email="ana@email.com")
session.add(usuario)
session.commit()
Também faço consultas simples com:
usuario = session.get(Usuario, 1)
E filtros mais complexos com:
from sqlmodel import select
usuarios = session.exec(select(Usuario).where(Usuario.nome == "Ana")).all()
Isso me dá controle para criar, ler, atualizar e deletar dados facilmente.
Boas Práticas de Segurança no Ambiente
Quando criei meu ambiente com FastAPI e PostgreSQL, foquei muito em manter a segurança. Isso envolve cuidar bem das informações sensíveis e garantir que cada serviço funcione isoladamente para evitar problemas.
Gerenciamento Seguro de Segredos
Eu nunca deixo senhas ou chaves diretamente no código. Uso arquivos .env
que ficam fora do repositório Git e configuro o Docker para ler essas variáveis durante a execução. Assim, as credenciais do banco de dados ou tokens de API não ficam expostos.
Além disso, prefiro ferramentas como Docker Secrets para armazenar senhas em produção. Elas ajudam a manter os segredos criptografados e acessíveis só para o container que precisa.
Também reviso regularmente os segredos usados para garantir que não estejam vazando em logs ou erros.
Isolamento de Serviços
Separei os containers para cada função: um para o FastAPI, outro para o PostgreSQL e outro, quando necessário, para serviços auxiliares.
Cada container roda em sua própria rede Docker, o que impede que um serviço acesse outro sem permissão explícita.
Configurar limites de recursos e definir permissões restritas para cada container ajuda a limitar o impacto de uma possível falha.
O isolamento facilita a atualização ou o reinício de uma parte do sistema sem afetar todo o ambiente.
Desenvolvimento e Hot Reload
Durante o desenvolvimento, a rapidez para ver as mudanças no código é essencial. Usei algumas técnicas para garantir que meu servidor atualizasse automaticamente sempre que eu fizesse modificações.
Configurando Auto-reload para FastAPI
O FastAPI oferece suporte nativo para auto-reload usando o Uvicorn, o servidor ASGI mais comum para rodar aplicações Python. Eu executei o comando abaixo para ativar essa função no meu ambiente de desenvolvimento:
uvicorn main:app --reload
O parâmetro --reload
faz com que o servidor reinicie automaticamente ao detectar qualquer alteração no código. Isso evita que eu precise parar e iniciar o servidor manualmente a cada mudança.
Além disso, o reload só deve ser usado em ambiente de desenvolvimento, pois pode afetar a performance e não é seguro em produção. Para garantir isso, mantenho a flag --reload
apenas localmente, nunca no deploy.
Testando o Ambiente de Desenvolvimento
Para garantir que meu ambiente funcione bem, precisei realizar testes que verificassem a integração entre os serviços e a confiabilidade dos contêineres usados. Isso me ajudou a identificar erros e confirmar que o FastAPI e o PostgreSQL se comunicam corretamente.
Testes de Integração com Docker
Os testes de integração focam em validar a conexão entre a aplicação FastAPI e o banco de dados PostgreSQL dentro dos contêineres Docker. Primeiro, executo comandos para subir os serviços com o Docker Compose, garantindo que ambos iniciem sem erros.
Uso scripts em Python que fazem requisições HTTP ao FastAPI, verificando se os dados são armazenados e recuperados corretamente no banco. Testo endpoints como criação, leitura, atualização e exclusão (CRUD). Assim, confirmo que a API responde bem em um ambiente que simula o real.
Dessa forma, erro no link do banco ou na configuração do Docker são detectados rapidamente.
Utilização de Test Containers
Test Containers são contêineres temporários criados apenas para rodar testes e podem ser programados para se autoapagarem após o uso. Usei essa técnica para evitar que o ambiente de desenvolvimento ficasse lento ou com dados antigos.
Com essa abordagem, consigo isolar cada teste, criando uma instância limpa do banco PostgreSQL para cada execução. Isso garante que os testes não interfiram uns nos outros.
Além disso, os Test Containers facilitam testar novas versões do banco ou da aplicação sem afetar o projeto principal. Para mim, isso tornou o processo mais ágil e seguro, com menos risco de falhas imprevistas.
Monitoramento e Logs nos Contêineres
Manter o controle dos logs e do desempenho dos contêineres é essencial para identificar problemas e garantir que tudo funcione corretamente. Eu uso técnicas práticas para capturar informações e monitorar recursos sem comprometer o desempenho do ambiente.
Captura e Visualização de Logs
Para coletar os logs dos contêineres, configurei o Docker para exportar as saídas padrão (stdout e stderr) dos serviços. Isso pode ser feito diretamente no docker-compose.yml
usando o driver de logs padrão ou ferramentas externas.
Uso comandos como docker logs [nome_do_container]
para acessar rapidamente os registros quando preciso. Para facilitar, instalei o Logspout, que encaminha os logs para um destino centralizado, melhorando a visualização.
Também utilizei o Portainer, que possui uma interface gráfica simples para ver os logs em tempo real, sem precisar acessar o terminal. Essa prática me ajuda a detectar erros no FastAPI e consultar queries do PostgreSQL rápido.
Ferramentas de Monitoramento Leves
Escolhi ferramentas leves para monitorar CPU, memória e uso de rede dos contêineres, sem sobrecarregar o sistema.
O cAdvisor do Google foi uma boa opção, pois coleta métricas e fornece relatórios detalhados em uma interface web simples. Ele roda em um contêiner separado e monitora automaticamente todos os outros.
Outra ferramenta útil é o Prometheus, configurado para puxar métricas dos contêineres. Com ele, criei alertas básicos para consumo excessivo de recursos.
Essas soluções me permitiram manter a saúde do ambiente sem afetar a performance das aplicações no FastAPI e PostgreSQL.
Debug e Diagnóstico em Ambientes Docker
Para resolver problemas em ambientes Docker, uso principalmente comandos que me ajudam a acessar o estado interno dos contêineres e entender o que está acontecendo. Observar logs e executar comandos diretamente dentro do contêiner é essencial para identificar erros e ajustar configurações.
Acesso Interativo aos Contêineres
Eu acesso o terminal dos contêineres usando o comando docker exec
. Isso permite que eu rode comandos dentro do contêiner ativo, como se estivesse em uma máquina local.
Exemplo básico:
docker exec -it nome_do_container bash
Com isso, consigo verificar arquivos, processos e configurações diretamente. No caso do FastAPI e PostgreSQL, uso para inspecionar logs, testar conexões e analisar erros.
Se o contêiner não tiver bash, uso sh
no lugar. Esse acesso é fundamental para detectar problemas que não aparecem só com os logs.
Gerenciamento de Dependências e Versionamento
Manter o controle das dependências e garantir compatibilidade são pontos essenciais para um ambiente estável. Eu usei ferramentas que facilitam a instalação e atualização das bibliotecas necessárias para o projeto.
Utilização de Arquivos requirements.txt e pyproject.toml
No começo, utilizei o requirements.txt para listar todas as dependências do projeto. Esse arquivo é simples, contendo nomes e versões específicas, o que ajuda na replicação exata do ambiente. Por exemplo:
fastapi==0.95.0
uvicorn==0.22.0
psycopg2-binary==2.9.6
Depois, optei por usar o pyproject.toml para gerenciar dependências e configurar o projeto de forma mais moderna, especialmente para o Poetry. Esse arquivo traz vantagens como o controle mais detalhado das versões e uma forma integrada de construir e publicar o pacote.
Ele permite definir versões mínimas ou intervalos, garantindo maior flexibilidade sem quebrar a compatibilidade. Isso facilita a manutenção do projeto a longo prazo.
Atualizações e Compatibilidade
Para manter as dependências atualizadas, eu consulto regularmente as versões estáveis das bibliotecas. Uso comandos como pip list --outdated
para identificar atualizações disponíveis.
Antes de atualizar, verifico o changelog para evitar mudanças que possam quebrar o código. Atualizo sempre em ambiente de desenvolvimento para testar antes de colocar em produção.
Quando uso o Poetry com o pyproject.toml, o comando poetry update
ajuda a manter as versões compatíveis automaticamente, respeitando os limites definidos.
Esse cuidado evita erros inesperados e mantém o ambiente alinhado com as melhores práticas e segurança.
Configuração para Desenvolvimento Colaborativo
Para que o time trabalhe de forma alinhada e eficiente, configurei o ambiente para evitar conflitos e garantir que todos usem as mesmas ferramentas e versões. A organização das regras e dos processos facilita entregas consistentes e reduz erros durante o desenvolvimento.
Padronização do Ambiente
Usei o Docker para criar um ambiente padronizado que funciona igual para todos. Isso inclui a mesma versão do Python, FastAPI e PostgreSQL, além das dependências específicas do projeto.
Criei um arquivo docker-compose.yml
para orquestrar os serviços. Assim, basta rodar um comando para levantar o ambiente completo, sem precisar configurar localmente.
Também configurei um arquivo .env.example
com variáveis de ambiente essenciais. Cada membro da equipe copia esse arquivo, renomeia para .env
e pode alterar só o que é pessoal, evitando inconsistências.
Boas Práticas em Equipe
Defini algumas regras simples para manter o código organizado e evitar retrabalho. Por exemplo, usamos o GitFlow para organizar branches e facilitar revisões.
Também combinamos de sempre atualizar o Docker quando houver mudanças nas dependências. Isso mantém o ambiente sincronizado para todo mundo.
Além disso, criamos um checklist de revisão antes de cada merge. Nele, verificamos itens como testes passando, documentação atualizada e código claro. Isso ajuda a manter o padrão e a qualidade do projeto.
Preparando para Deploys em Produção
Para garantir que o ambiente esteja pronto para um uso real, é fundamental ajustar a configuração do Docker e gerenciar as variáveis de ambiente corretamente. Isso ajuda a manter a segurança e melhora a performance da aplicação quando ela estiver no ar.
Ajustes no Dockerfile e no Compose
No Dockerfile, troque a imagem base para uma mais leve, como python:3.11-slim
. Isso diminui o tamanho da imagem e acelera o deploy.
Use um arquivo separado para produção no Docker Compose, por exemplo, docker-compose.prod.yml. Nele, habilito volumes só se preciso e configuro redes externas para facilitar o acesso.
Também removo instalações desnecessárias e uso multi-stage builds para separar a construção da aplicação e da imagem final. Isso ajuda a evitar arquivos temporários que apenas aumentam o peso da imagem.
Variáveis de Ambiente para Produção
No ambiente de produção, não uso variáveis diretamente no Compose. Prefiro carregar tudo via um arquivo .env.prod que inclua senhas, chaves secretas e configurações específicas.
Sempre defino variáveis para banco, porta, e segredo de JWT fora do código-fonte para aumentar a segurança.
Um exemplo básico de variáveis para produção:
POSTGRES_DB=meubanco
POSTGRES_USER=usuario_prod
POSTGRES_PASSWORD=senha_super_secreta
SECRET_KEY=uma_chave_complexa
Mantenho esses arquivos em um local seguro e os adiciono ao .gitignore
para não vazar dados sensíveis no controle de versão.
Principais Desafios e Como Resolvi
Durante a criação do ambiente, enfrentei problemas que afetaram a comunicação entre serviços e a guarda dos dados. Foi preciso ajustar configurações para garantir que tudo funcionasse de forma estável e segura.
Resolução de Conflitos de Portas
O primeiro desafio surgiu quando o Docker tentou usar portas que já estavam ocupadas no meu computador. Isso causava falhas ao iniciar os containers do FastAPI e do PostgreSQL.
Para resolver, verifiquei quais portas estavam em uso com o comando netstat -tuln
. Em seguida, ajustei o arquivo docker-compose.yml
, alterando as portas expostas para valores disponíveis. Por exemplo, mudei a porta padrão 5432 do PostgreSQL para 5433, garantindo que nenhum outro serviço estivesse utilizando.
Além disso, configurei o FastAPI para escutar a porta correta e garantir comunicação com o banco. Esses ajustes permitiram iniciar os containers sem erro e evitaram conflitos futuros durante o desenvolvimento.
Persistência de Dados
Manter os dados do PostgreSQL mesmo após parar ou reiniciar os containers foi fundamental para mim. Inicialmente, percebi que os dados eram perdidos porque não defini volumes persistentes.
Para corrigir, criei um volume Docker no docker-compose.yml
, que mapeava uma pasta local ou volume Docker para o diretório de dados do PostgreSQL (/var/lib/postgresql/data
).
services:
db:
image: postgres
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Isso garantiu que os registros da aplicação não fossem apagados. Também configurei permissões corretas para evitar problemas de leitura e escrita dentro do container. Dessa forma, assegurei que meu ambiente tivesse um banco confiável e consistente entre reinicializações.
Considerações Finais e Próximos Passos
Durante o processo de criação do ambiente com FastAPI, PostgreSQL e Docker, percebi como a automação simplifica minhas tarefas diárias. O uso do Docker permitiu uma configuração rápida e consistente, o que facilita o desenvolvimento e a colaboração.
Agora que o ambiente está funcionando, meu próximo objetivo é integrar testes automatizados. Isso ajudará a garantir que o código esteja sempre funcionando antes de ser enviado para produção.
Também quero explorar a escalabilidade do sistema usando Docker Compose para orquestração mais avançada. Ela permitirá gerenciar múltiplos serviços e facilitará o desenvolvimento de aplicações maiores.
Para manter a segurança, pretendo adicionar controle de acesso e variáveis de ambiente protegidas. Isso é essencial para projetos que lidam com dados sensíveis.
Segue uma lista dos próximos passos que considero importantes:
- Implementar testes unitários e teste de integração.
- Fazer monitoramento básico dos containers.
- Automatizar deploy usando pipelines.
- Melhorar documentação do ambiente.
Esses passos vão ajudar a deixar o ambiente mais robusto e profissional. Continuar estudando e praticando é o melhor caminho para evoluir nesse tipo de projeto.