CI/CD para Flask: automatize o Deploy da sua API com Docker e GitHub Actions

Rocketseat

Navegação Rápida:
Já cansou de fazer deploy manual toda vez que atualiza seu código? Aquela sensação de "será que esqueci alguma coisa?" ou "por que funciona na minha máquina e não no servidor?" é familiar?
Bora acabar com isso agora!
Você vai aprender a criar um pipeline de CI/CD completo que automatiza todo o processo de build e deploy da sua API Python Flask usando Docker e GitHub Actions. No final, cada
git push
que você fizer vai desencadear um processo automático que empacota e disponibiliza sua aplicação.O melhor de tudo? Você não precisa ser especialista em DevOps para fazer isso acontecer.
O que você vai construir
Um pipeline automatizado que:
- Detecta mudanças no seu código automaticamente
- Cria uma imagem Docker otimizada da sua aplicação
- Faz o push dessa imagem para um registro (Docker Hub)
- Deixa tudo pronto para o deploy em qualquer ambiente
O que você precisa saber antes
- Familiaridade com Docker (saber criar um container básico)
- Uma conta no GitHub
- Uma conta no Docker Hub (para armazenar suas imagens)
- Vontade de automatizar suas entregas
Bora começar? 🚀
Entendendo CI/CD
CI/CD é um conjunto de práticas que mudam o jogo no desenvolvimento de software. Mas o que significa na prática?
CI: Continuous Integration (integração contínua)
Imagine que você e outras pessoas estão trabalhando no mesmo projeto. Cada um faz suas alterações e envia para o repositório principal (no GitHub, por exemplo).
A integração contínua é o processo de juntar essas alterações automaticamente e frequentemente. A cada novo commit, o sistema verifica se o novo código funciona bem com o código existente. Isso geralmente envolve rodar testes automatizados.
Benefício: você descobre bugs e conflitos muito mais cedo, antes que eles virem uma bola de neve.
CD: Continuous Delivery ou Continuous Deployment (entrega ou deploy contínuo)
Depois que o código passa pela integração (CI), entra o CD.
- Continuous Delivery (entrega contínua): significa que seu código está testado, empacotado e pronto para ir para produção a qualquer momento. O deploy final ainda pode ser manual, mas o pacote está pronto.
- Continuous Deployment (deploy contínuo): leva isso um passo adiante. Se o código passar por todos os testes, ele é automaticamente enviado para produção, sem intervenção humana.
Neste material, vamos focar em preparar o terreno para o CD, automatizando o build e o empacotamento da nossa aplicação Flask em uma imagem Docker.
Benefício: você entrega valor mais rápido, com menos erros manuais e muito mais confiança no seu processo.
Preparando a API Flask
Vamos começar criando uma API Flask super simples. O foco aqui não é o Python, mas sim o processo de automação.
Se você está começando com Python ou quer reforçar os conceitos de Flask, você pode criar sua própria API seguindo o curso gratuito da Rocketseat: Introdução ao Python e Flask.
Estrutura do projeto
Crie uma pasta para o projeto. Sua estrutura inicial ficará assim:
flask-cicd-pipeline/ ├── app.py └── requirements.txt
O código da API
Crie o arquivo
app.py
e adicione o seguinte código. É uma API com uma única rota para teste.from flask import Flask, jsonify app = Flask(__name__) @app.route('/') def index(): return jsonify({"message": "Deploy automatizado funcionando! 🚀", "status": "success"}) # O bloco abaixo só é usado local. if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)
Dependências
Para rodar nossa aplicação em um ambiente de produção (como um container Docker), é recomendado usar um servidor web mais robusto que o servidor de desenvolvimento do Flask. Usaremos o
gunicorn
.Crie o arquivo
requirements.txt
e adicione:Flask>=3.0.0 gunicorn
Você pode testar localmente instalando as dependências (preferencialmente em um ambiente virtual) e rodando
python app.py
.Criando o Dockerfile
Agora vamos "containerizar" nossa aplicação. O Dockerfile é a receita que diz ao Docker como construir a imagem da nossa API Flask.
Crie um arquivo chamado
Dockerfile
(sem extensão) na raiz do projeto.Vamos construir o
Dockerfile
passo a passo, focando em otimização de camadas:# 1. Imagem base: Começamos com uma imagem Python oficial e leve. # 'slim' significa que ela tem apenas o necessário para rodar Python. FROM python:3.11-slim # 2. Diretório de trabalho: Define onde o código vai ficar dentro do container. WORKDIR /app # 3. Instalação de dependências: # Copiamos apenas o requirements.txt primeiro. Isso otimiza o cache do Docker. # Se o código mudar, mas os requisitos não, essa etapa não precisa ser refeita. COPY requirements.txt . # Rodamos o pip para instalar as dependências. # '--no-cache-dir' ajuda a manter a imagem final menor. RUN pip install --no-cache-dir -r requirements.txt # 4. Código da aplicação: Copiamos o restante dos arquivos do nosso projeto. COPY . . # 5. Exposição de porta: Informamos ao Docker que nossa aplicação vai usar a porta 5000. EXPOSE 5000 # 6. Comando de inicialização: O que o container deve fazer quando iniciar. # Usamos gunicorn para servir nossa aplicação Flask. # '--bind 0.0.0.0:5000' faz a aplicação escutar em todas as interfaces na porta 5000. # 'app:app' diz ao gunicorn para procurar o objeto 'app' dentro do módulo 'app.py'. CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
Como testar o container localmente
Antes de automatizar, é sempre bom garantir que o Dockerfile funciona na sua máquina.
- Build da imagem:
No terminal, dentro da pasta do projeto, rode o comando para construir a imagem. Vamos chamá-la de
flask-api-cicd
.
docker build -t flask-api-cicd .
Rodar o container:
Agora, vamos iniciar um container a partir dessa imagem. Mapeamos a porta 5000 do host para a porta 5000 do container.
docker run -p 5000:5000 flask-api-cicd
Abra seu navegador em
http://localhost:5000
. Você deve ver a mensagem da API. Sucesso! Configurando o GitHub Actions
Chegou a hora da mágica acontecer. O GitHub Actions é a ferramenta de CI/CD integrada ao GitHub que nos permite automatizar fluxos de trabalho (workflows).
Componentes principais
- Workflow: o processo automatizado completo que você define.
- Trigger (gatilho): o evento que inicia o workflow (ex: um
push
na branchmain
).
- Job: um conjunto de passos que rodam em um ambiente.
- Step (passo): uma tarefa individual dentro de um job (ex: rodar um comando).
Criando o arquivo de workflow
Os workflows ficam em uma pasta específica no seu repositório. Crie a estrutura de diretórios
.github/workflows/
na raiz do seu projeto, e dentro dela, crie o arquivo deploy.yml
.flask-cicd-pipeline/ ├── .github/ │ └── workflows/ │ └── deploy.yml ├── app.py ├── Dockerfile └── requirements.txt
Configuração do workflow
Vamos criar um workflow que faz o build da imagem Docker e envia para o Docker Hub toda vez que houver um push na branch
main
.Abra o
deploy.yml
e adicione o seguinte conteúdo:name: CI/CD Pipeline - Build and Push Docker Image # Triggers: Define quando o workflow será executado on: push: branches: [ "main" ] # Apenas na branch main pull_request: branches: [ "main" ] # Também roda quando um PR for aberto contra a main # Jobs: Os trabalhos que serão executados jobs: build-and-push: # Define o ambiente onde o job vai rodar (uma máquina virtual Ubuntu) runs-on: ubuntu-latest # Steps: Os passos do job steps: # Passo 1: Checkout do código # Usa uma action pronta para baixar o código do repositório para a máquina virtual - name: Checkout code uses: actions/checkout@v4 # Passo 2: Login no Docker Hub # Precisamos fazer login para poder enviar a imagem para o registro - name: Login to Docker Hub # Só executa este passo se for um push na main (não em PRs) if: github.event_name == 'push' uses: docker/login-action@v3 with: # Usamos secrets do GitHub para armazenar credenciais de forma segura username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} # Passo 3: Configurar o Docker Buildx # Buildx é uma ferramenta avançada do Docker para builds mais eficientes - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 # Passo 4: Build e Push da imagem # A action principal que faz o trabalho pesado - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: . # Onde está o Dockerfile (na raiz) # Só faz o push se for um push na main. Em PRs, apenas faz o build (para verificar se funciona) push: ${{ github.event_name == 'push' }} # Define o nome e a tag da imagem. Ex: seuusuario/flask-api-cicd:latest tags: ${{ secrets.DOCKERHUB_USERNAME }}/flask-api-cicd:latest
Explicação do workflow
- Adicionamos
pull_request
nos triggers. Isso é uma boa prática de CI: verificar se o código do PR consegue ser integrado antes do merge.
- Usamos
if: github.event_name == 'push'
para garantir que o login e o push para o Docker Hub só aconteçam quando o código for efetivamente enviado para amain
, não durante a verificação de um PR.
Secrets e variáveis de ambiente
Você percebeu que usamos
${{ secrets.DOCKERHUB_USERNAME }}
e ${{ secrets.DOCKERHUB_TOKEN }}
? Não podemos colocar nossas credenciais direto no código. O GitHub Secrets é um cofre seguro para guardar essas informações.- Crie um token no Docker Hub:
- Vá em Docker Hub > Account Settings > Security.
- Clique em "New Access Token".
- Dê um nome (ex: "github actions token") e gere o token.
- Importante: Copie ele agora! Você só verá ele uma vez.
- Configure no GitHub:
- No seu repositório no GitHub (você precisará subir o código que criamos até agora), vá em Settings > Secrets and variables > Actions.
- Clique em "New repository secret".
- Crie
DOCKERHUB_USERNAME
com seu nome de usuário do Docker Hub. - Crie
DOCKERHUB_TOKEN
com o token que você copiou do Docker Hub.
Testando o pipeline
Tudo configurado! Agora vamos ver a automação funcionando na prática.
Como fazer um commit que vai acionar o workflow
- Certifique-se de que seu projeto está no GitHub.
- Faça uma pequena alteração (opcional). Se quiser testar a atualização, mude a mensagem no
app.py
:
return jsonify({"message": "Pipeline CI/CD atualizado! 💜", "status": "success"})
- Commit e Push:
Certifique-se de que todos os arquivos (incluindo o diretório
.github/workflows
) foram adicionados e faça o push para a branchmain
.
git add . git commit -m "feat: configura pipeline CI/CD" git push origin main
Onde visualizar os logs no GitHub Actions
Assim que você fizer o push, o GitHub Actions vai detectar a mudança e iniciar o workflow.
- Vá para a aba "Actions" no seu repositório do GitHub.
- Você verá seu workflow listado, provavelmente com um ícone amarelo indicando que está em execução.
- Clique nele para ver os detalhes e acompanhar os logs de cada step em tempo real.
Como interpretar sucessos e falhas
- Sucesso (Verde ✅): Parabéns! Sua imagem Docker foi construída e enviada para o Docker Hub.
- Falha (Vermelho ❌): Não se preocupe. Clique no passo que falhou para ler os logs. O GitHub Actions fornece logs detalhados que geralmente apontam a causa do problema.
Debug de problemas comuns
- Falha no login do Docker Hub: verifique se as secrets (
DOCKERHUB_USERNAME
eDOCKERHUB_TOKEN
) estão corretas no GitHub. Lembre-se que o token não é sua senha normal.
- Falha no build: pode haver um erro no seu
Dockerfile
ou no código da aplicação. Leia os logs do step "Build and push Docker image". Teste o build localmente primeiro.
- Workflow não inicia: verifique se o arquivo está em
.github/workflows/deploy.yml
e se o trigger está configurado para a branch correta (main
).
Próximos passos e melhorias
Você construiu um pipeline de CI/CD funcional, mas isso é só o começo da sua jornada em DevOps. Existem várias melhorias que você pode implementar:
Adicionar testes automatizados
Este é talvez o passo mais importante para um CI robusto. Antes de fazer o build da imagem, você deve rodar seus testes (com
pytest
, por exemplo). Se os testes falharem, o pipeline deve parar.Implementar diferentes ambientes
Você pode configurar workflows diferentes para branches diferentes. Por exemplo, a branch
develop
faz deploy em um ambiente de staging (teste), e a branch main
faz deploy em produção.Deploy (CD real)
Nosso pipeline atual faz o build e o push da imagem. O próximo passo seria adicionar um step final para fazer o deploy dessa imagem em um servidor, um cluster Kubernetes ou um serviço de nuvem (como AWS ECS, Azure Container Apps ou Google Cloud Run).
Adicionar notificações e rollback
Você pode configurar o pipeline para te notificar sobre falhas e implementar mecanismos de rollback automático caso a nova versão apresente problemas em produção.
Conclusão
Automatizar o deploy não precisa ser complicado. Com ferramentas como Docker e GitHub Actions, você pode criar pipelines robustos que economizam tempo, reduzem erros e aumentam a confiança no seu código. Você deu um passo super importante hoje.
De Automatizador a Arquiteto de Infraestrutura Cloud
O pipeline que você construiu hoje é a porta de entrada para o mundo DevOps. Ele resolve o deploy. Mas a verdadeira maestria está em orquestrar todo o ecossistema que vem antes e depois.
Na Formação DevOps da Rocketseat, você vai transformar seu conhecimento em domínio:
- Orquestre centenas de containers como o que você acabou de criar usando Kubernetes, a ferramenta padrão da indústria para escalar aplicações.
- Defina toda a sua infraestrutura como código com Terraform, para criar e destruir ambientes completos na AWS, Azure ou GCP com um único comando.
- Monitore suas aplicações com Prometheus e Grafana, para antecipar problemas antes que eles afetem seus usuários.
Este é o caminho para se tornar o profissional que não apenas aperta o botão de deploy, mas que projeta, constrói e mantém a infraestrutura resiliente que sustenta as maiores empresas de tecnologia.
Artigos_
Explore conteúdos relacionados
Descubra mais artigos que complementam seu aprendizado e expandem seu conhecimento.