Guia de CI/CD para Java no AWS ECS com GitHub Actions
Configurar um pipeline de CI/CD para Java no AWS ECS é o caminho ideal para automatizar deploys de microsserviços.

A entrega manual de software gera erros graves, atrasos crônicos e estresse desnecessário para o time de desenvolvimento. No ecossistema corporativo atual, a automação não é mais um diferencial competitivo, mas sim um requisito de sobrevivência técnica. Quando combinamos a robustez do ecossistema Java com a escalabilidade do AWS ECS, alcançamos um patamar de estabilidade operacional incrível para qualquer aplicação corporativa de alta performance.

No entanto, a configuração inicial dessa infraestrutura costuma assustar muitos profissionais de tecnologia. A complexidade na integração entre repositórios de código, registros de container e orquestradores de nuvem cria uma barreira de entrada significativa. Felizmente, o GitHub Actions simplifica essa jornada ao unificar o controle de versão e a automação de deploy em uma única ferramenta visual, declarativa e extremamente poderosa.

Por que usar AWS ECS com Fargate para aplicações Spring Boot?

O AWS ECS gerencia containers Docker de forma nativa e extremamente integrada à infraestrutura da Amazon Web Services. Quando associamos o ECS ao modelo de computação serverless AWS Fargate, eliminamos totalmente a necessidade de provisionar e gerenciar servidores virtuais EC2. Dessa forma, você foca exclusivamente no desenvolvimento de código funcional e deixa o provisionamento de hardware por conta da AWS.

Portanto, as aplicações Java baseadas em Spring Boot se beneficiam imensamente dessa arquitetura elástica. O Spring Boot entrega microsserviços empacotados em arquivos JAR autossuficientes, que se transformam de forma muito natural em imagens Docker otimizadas. Juntando esses fatores, o deploy no ECS com Fargate reduz os custos operacionais de infraestrutura e simplifica consideravelmente as políticas de escalabilidade horizontal automáticas.

Além disso, o ECS oferece suporte nativo ao recurso de rolling updates. Esse mecanismo atualiza suas tarefas gradualmente, direcionando o tráfego da rede apenas para os novos containers saudáveis. Por conseguinte, o seu usuário final nunca experimentará interrupções ou lentidão durante o lançamento de novas funcionalidades do sistema.

O papel do GitHub Actions no fluxo de entrega contínua

O GitHub Actions se consolidou como uma das ferramentas de integração e entrega contínuas (CI/CD) mais populares do mercado global de TI. Primeiramente, ele dispensa a necessidade de manter servidores Jenkins locais, reduzindo custos de manutenção. Em segundo lugar, a ferramenta oferece uma infinidade de ações prontas criadas por parceiros oficiais na AWS Marketplace.

Dessa forma, criamos fluxos de trabalho declarativos através de arquivos YAML simples armazenados no próprio repositório do projeto. Essa abordagem de Pipeline as Code facilita o versionamento de toda a sua esteira de automação. Como resultado, qualquer alteração no processo de deploy passa por revisões de código de forma transparente.

Preparando a aplicação Java Spring Boot para o Docker

Antes de criarmos o pipeline, precisamos garantir que nossa aplicação Java seja devidamente empacotada em uma imagem Docker eficiente. Para projetos Spring Boot modernos, o ideal é utilizarmos imagens base leves que reduzam o tamanho final do arquivo gerado. Imagens menores aceleram o upload para o registro de containers e diminuem o tempo de inicialização na AWS.

Abaixo, apresentamos uma estrutura de arquivo Dockerfile otimizada para aplicações Spring Boot que utilizam as novas virtual threads no Java de forma eficiente. Esse arquivo utiliza o conceito de multi-stage build para separar a fase de compilação do ambiente de execução final.

# Estágio de Compilação
FROM maven:3.9-eclipse-temurin-21 AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package -DskipTests

# Estágio de Execução
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=build /home/app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Note que utilizamos a versão do Eclipse Temurin baseada no Alpine Linux. Essa escolha reduz drasticamente a superfície de ataque de segurança do container e mantém o tamanho da imagem abaixo de 200MB. Além disso, a separação de estágios garante que ferramentas de compilação como o Maven não sejam incluídas na imagem de produção.

Estruturando o Pipeline de CI/CD com GitHub Actions

Agora que nossa aplicação já está conteinerizada, podemos projetar o arquivo de configuração do GitHub Actions. O arquivo deve ser criado no caminho .github/workflows/deploy.yml do seu repositório. O fluxo completo será dividido em duas fases principais: a fase de integração contínua (CI) e a fase de entrega contínua (CD).

Fase do Pipeline Ferramentas Utilizadas Resultado Esperado
Build e Testes JDK 21, Maven/Gradle Código validado e empacotado
Segurança SonarQube / Trivy Varredura de vulnerabilidades concluída
Publicação Docker, AWS ECR Imagem enviada ao registro privado AWS
Deploy AWS ECS, GitHub Actions Containers atualizados sem downtime

Para interagir com os serviços da nuvem AWS com segurança, recomendamos fortemente o uso do protocolo OIDC (OpenID Connect). O OIDC elimina a necessidade de armazenar credenciais de acesso permanentes (como AWS Access Keys) nos segredos do GitHub. Em vez disso, o GitHub Actions solicita credenciais temporárias de curta duração diretamente ao IAM da AWS para cada execução.

O arquivo YAML de configuração passo a passo

Abaixo, apresentamos o esqueleto estrutural do pipeline completo de deploy. Certifique-se de configurar as variáveis de ambiente corretas para o seu cluster ECS e repositório ECR nas configurações do seu repositório GitHub.

name: Deploy Java Application to AWS ECS

on:
  push:
    branches:
      - main

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Set up JDK 21
        uses: actions/setup-java@v4
        with:
          java-version: '21'
          distribution: 'temurin'
          cache: 'maven'

      - name: Build with Maven
        run: mvn clean package -DskipTests

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
          aws-region: us-east-1

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: minha-app-java
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

      - name: Fill in the new image ID in the Amazon ECS task definition
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          task-definition: task-definition.json
          container-name: minha-app-java
          image: ${{ steps.build-image.outputs.image }}

      - name: Deploy Amazon ECS task definition
        uses: aws-actions/amazon-ecs-deploy-task-definition@v2
        with:
          task-definition: ${{ steps.task-def.outputs.task-definition }}
          service: meu-servico-ecs
          cluster: meu-cluster-ecs
          wait-for-service-stability: true

Esse workflow executa de forma sequencial e segura. No final do processo, a ação de deploy aguarda que o novo container informe que está saudável (health check positivo) antes de desativar a versão antiga. Essa verificação rigorosa garante que nenhuma versão quebrada do código chegue a ficar ativa para os seus usuários finais.

Como mitigar riscos de downtime no deploy de microsserviços Spring Boot

Embora a automação reduza erros humanos, a atualização de sistemas distribuídos sempre envolve riscos inerentes à rede e ao banco de dados. Para garantir um deploy 100% livre de indisponibilidade, você precisa configurar corretamente as diretivas de capacidade do seu serviço ECS. Essas diretivas controlam quantos containers podem rodar simultaneamente durante a transição de versões.

Primeiramente, configure a propriedade Minimum Healthy Percent para 100%. Isso sinaliza ao ECS que ele nunca deve desligar um container antigo antes que o novo container correspondente esteja ativo e saudável. Em segundo lugar, defina o Maximum Percent para 200%, permitindo que o ECS dobre temporariamente a capacidade de instâncias durante o processo de deploy.

Adicionalmente, certifique-se de configurar um Health Check robusto no seu Application Load Balancer (ALB). O Spring Boot possui o módulo Spring Boot Actuator, que fornece um endpoint nativo de verificação de saúde no caminho /actuator/health. Configure o seu target group na AWS para monitorar esse endpoint específico antes de considerar a nova tarefa pronta para receber requisições externas.

Perguntas frequentes

Como funciona a autenticação via OIDC do GitHub no AWS IAM?

O OIDC permite que o GitHub Actions se autentique na AWS sem armazenar chaves de acesso permanentes em seus repositórios. O GitHub fornece um token JSON Web Token (JWT) temporário e assinado para cada execução. Por fim, a AWS valida este documento e emite credenciais de curta duração com permissões restritas e seguras.

Qual a diferença entre o ECS com EC2 e o ECS com Fargate?

No ECS com EC2, você gerencia e escala manualmente o cluster de servidores virtuais que rodam os containers Docker de forma direta. No ECS com Fargate, a AWS gerencia toda a infraestrutura física de forma totalmente serverless. Assim, você paga apenas pelos recursos de CPU e memória que seus containers de fato consomem.

Como lidar com variáveis de ambiente sensíveis e segredos no ECS?

Informações confidenciais, como senhas de banco de dados e chaves de API, nunca devem ser expostas no Dockerfile. Portanto, armazene esses dados no AWS Secrets Manager ou no Parameter Store do SSM. Em seguida, injete esses valores sensíveis diretamente como variáveis de ambiente na sua task-definition do ECS.

Conclusão

Implementar uma esteira automatizada de CI/CD para aplicações Java no AWS ECS transforma a rotina técnica do seu time de desenvolvimento. Esse processo garante entregas previsíveis, rápidas e sem qualquer impacto negativo na experiência de uso do cliente final. Combinando as forças do GitHub Actions e do AWS Fargate, você foca nos códigos e na lógica de negócios enquanto a nuvem cuida do resto.

Quer aprofundar seus conhecimentos em engenharia de software na nuvem e dominar novas ferramentas de infraestrutura moderna? Acesse a nossa página de tutoriais e leia o nosso artigo detalhado sobre o Spring Boot Actuator e Prometheus no Kubernetes para aprender a monitorar seus microsserviços em produção como um especialista hoje mesmo.

Como monitorar e validar o deploy de Java no AWS ECS

Realizar o deploy com GitHub Actions é apenas o primeiro passo para o sucesso da sua pipeline. Posteriormente, você precisa garantir que a nova versão do seu microsserviço Spring Boot está rodando sem erros no AWS ECS.

Dessa forma, a integração de verificações de saúde (health checks) evita que códigos instáveis fiquem ativos para os usuários. A tabela abaixo apresenta as principais métricas que você deve acompanhar logo após o deploy:

Métrica de Validação Ferramenta Indicada Objetivo Principal
Disponibilidade da API Spring Boot Actuator Verificar se o endpoint /actuator/health retorna o status UP.
Consumo de Memória AWS CloudWatch Garantir que a JVM não atinja o limite de memória da tarefa ECS.
Tempo de Inicialização GitHub Actions Logs Avaliar se o container Java iniciou dentro do prazo do health check.

Além disso, o uso de estratégias de deploy como o Rolling Updates no AWS ECS garante transições suaves. Isso significa que o ECS mantém a versão antiga ativa até que o novo container Java passe em todos os testes de inicialização.

Configuração ideal de recursos para containers Spring Boot

Muitos desenvolvedores enfrentam problemas de travamento de containers Java no AWS ECS devido à má configuração de recursos. Por isso, configurar corretamente os limites de CPU e memória evita que a JVM sofra com o encerramento inesperado do processo (Out Of Memory Killer).

Portanto, ao preparar o seu arquivo de definição de tarefa do ECS (task definition), reserve pelo menos 512 MB de RAM para aplicações Spring Boot simples. Para serviços mais robustos, o recomendável é iniciar com 1 GB ou 2 GB de RAM.

Perguntas frequentes

Como o GitHub Actions se autentica de forma segura no AWS ECS?

A autenticação segura é realizada por meio do protocolo OpenID Connect (OIDC). Portanto, essa abordagem elimina a necessidade de armazenar credenciais de longo prazo da AWS (como chaves de acesso do IAM) no repositório do GitHub. Dessa forma, o GitHub Actions assume temporariamente uma role do IAM criada especificamente para o deploy.

O que fazer quando o deploy do Java no AWS ECS falha por timeout?

Primeiramente, verifique se a aplicação Java não está travando durante a inicialização por falta de memória ou falha de conexão com o banco de dados. Em seguida, avalie se os tempos limites de health check configurados no seu Application Load Balancer (ALB) da AWS estão muito rígidos. Por fim, ajuste os tempos de carência de inicialização na definição do serviço do ECS para dar mais margem à JVM.

Como monitorar o consumo de recursos do Spring Boot no AWS ECS?

A melhor prática consiste em utilizar o Spring Boot Actuator em conjunto com o Prometheus para coletar métricas de JVM em tempo real. Além disso, as métricas nativas do AWS Container Insights fornecem uma visão detalhada do consumo de CPU e memória do ECS Fargate. Para saber mais sobre como integrar essas ferramentas de monitoramento, consulte a documentação oficial do Prometheus.

Conclusão

Implementar uma esteira de CI/CD para Java no AWS ECS usando GitHub Actions reduz drasticamente o trabalho manual e os erros em produção. Consequentemente, o seu time ganha velocidade e segurança para entregar novas funcionalidades de forma consistente.

Se você deseja acelerar o desenvolvimento de microsserviços modernos com alta escalabilidade, comece hoje mesmo a aplicar essas configurações no seu repositório. Aproveite para testar essas práticas agora mesmo criando um fluxo de deploy automatizado no seu projeto Spring Boot.

Leia também