Este guia fornecerá toda a teoria e os códigos completos para que os alunos possam containerizar a aplicação e orquestrá-la com um banco de dados de produção.
Objetivo: Ensinar o aluno a empacotar a aplicação Spring Boot e suas dependências em um container Docker, preparando-a para distribuição e execução em qualquer ambiente, do desenvolvimento à produção. Ao final, o aluno será capaz de orquestrar a aplicação junto com um banco de dados PostgreSQL usando docker-compose.
O Problema Clássico: “Mas funciona na minha máquina!” Todo desenvolvedor já passou por isso. A aplicação funciona perfeitamente em seu computador, mas quebra ao ser movida para o ambiente de testes ou produção. Isso acontece por diferenças de ambiente: versões do Java, bibliotecas do sistema operacional, variáveis de ambiente, etc.
A Solução: Containers Conceito-Chave: Um container é um pacote padronizado que agrupa o código da sua aplicação com todas as suas dependências (runtime do Java, bibliotecas, configurações). Ele é isolado do sistema operacional hospedeiro, garantindo que a aplicação se comporte da mesma forma em qualquer lugar.
Termos Essenciais do Docker:
Dockerfile.Principais Vantagens:
Dockerfile para a aplicação Spring BootConceito-Chave: Multi-Stage Build Para criar uma imagem otimizada, usaremos uma técnica chamada “multi-stage build”.
.jar..jar final do estágio anterior.O resultado é uma imagem final muito menor e mais segura, pois não contém código-fonte ou ferramentas de compilação.
Ação: Na raiz do seu projeto (na mesma pasta do pom.xml), crie um arquivo chamado Dockerfile (sem extensão).
Dockerfile (Arquivo Completo)# ----- ESTÁGIO 1: Build com Maven e JDK -----
# Usamos a imagem oficial do Maven que já contém o JDK 21
FROM maven:3.9-eclipse-temurin-21 AS builder
# Define o diretório de trabalho dentro do container
WORKDIR /app
# Copia os arquivos de configuração do Maven primeiro para aproveitar o cache do Docker
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
# Baixa as dependências
RUN mvn dependency:go-offline
# Copia o restante do código-fonte da aplicação
COPY src ./src
# Compila a aplicação, gera o .jar e pula os testes para acelerar o build da imagem
RUN mvn clean package -DskipTests
# ----- ESTÁGIO 2: Runtime com JRE -----
# Usamos uma imagem base leve, contendo apenas o Java Runtime Environment (JRE)
FROM eclipse-temurin:21-jre-jammy
# Define o diretório de trabalho
WORKDIR /app
# Copia apenas o arquivo .jar final do estágio de build para a nossa imagem final
COPY --from=builder /app/target/gestaodeestoques-0.0.1-SNAPSHOT.jar app.jar
# Expõe a porta 8080 para que possamos nos conectar ao nosso container de fora
EXPOSE 8080
# Comando que será executado quando o container iniciar
ENTRYPOINT ["java", "-jar", "app.jar"]
Ação: Agora, vamos construir e executar nosso container.
Construir a Imagem: Abra o terminal na raiz do projeto e execute o comando:
docker build -t gestao-estoque-api .
(O -t gestao-estoque-api dá um nome (tag) à nossa imagem. O . indica que o Dockerfile está no diretório atual.)
Executar o Container: Após o build terminar, execute o container com o comando:
docker run -p 8080:8080 gestao-estoque-api
(O -p 8080:8080 mapeia a porta 8080 da sua máquina para a porta 8080 exposta pelo container.)
Sua aplicação agora está rodando dentro de um container Docker! No entanto, ela ainda usa o banco H2 em memória, que é zerado a cada reinicialização.
docker-compose e PostgreSQLConceito-Chave: docker-compose é uma ferramenta para definir e executar aplicações Docker com múltiplos containers. Usamos um arquivo docker-compose.yml para descrever os serviços que compõem nossa aplicação (ex: a API e o banco de dados) e como eles se conectam.
Ação 1: Preparar a aplicação para se conectar ao PostgreSQL.
pom.xml (Adicionar Driver do PostgreSQL)<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
src/main/resources/application-prod.properties (Novo Arquivo para Perfil de Produção)# Configurações do Banco de Dados PostgreSQL
spring.datasource.url=jdbc:postgresql://postgres-db:5432/estoquedb
spring.datasource.username=admin
spring.datasource.password=admin123
spring.datasource.driver-class-name=org.postgresql.Driver
# Configura o Hibernate/JDBC para validar o schema (não criar/dropar tabelas)
spring.sql.init.mode=never
Ação 2: Criar o arquivo docker-compose.yml na raiz do projeto.
docker-compose.yml (Arquivo Completo)version: '3.8'
services:
# Serviço da nossa API Spring Boot
app-service:
# Constrói a imagem a partir do Dockerfile no diretório atual
build: .
# Mapeia a porta 8080 do host para a porta 8080 do container
ports:
- "8080:8080"
# Define as variáveis de ambiente para o container da aplicação
environment:
# Diz ao Spring para usar o perfil 'prod', ativando o application-prod.properties
- SPRING_PROFILES_ACTIVE=prod
# O segredo do JWT (em um projeto real, use um mecanismo de secrets)
- JWT_SECRET=7d4a1b0b3e6c9d8a3f4b2e1c0a9f8b7c6d5e4a3b2c1d0f9e8a7b6c5d4e3f2a1b
# Garante que o serviço do banco de dados inicie antes da nossa aplicação
depends_on:
- postgres-db
# Serviço do Banco de Dados PostgreSQL
postgres-db:
# Usa a imagem oficial do PostgreSQL
image: postgres:17
# Define as variáveis de ambiente para configurar o banco de dados
environment:
- POSTGRES_DB=estoquedb
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=admin123
# Mapeia a porta 5432 do container para a 5432 do host (opcional, para acesso externo)
ports:
- "5432:5432"
# Monta um volume para persistir os dados do banco
volumes:
- postgres-data:/var/lib/postgresql/data
# Define o volume nomeado para persistência dos dados
volumes:
postgres-data:
Conceito-Chave (Volumes): A linha volumes: - postgres-data:/var/lib/postgresql/data é crucial. Ela diz ao Docker para “salvar os dados do banco de dados do container em um local gerenciado pelo Docker no seu computador (postgres-data)”. Isso garante que, mesmo se o container for removido, seus dados estarão seguros.
Ação 3: Iniciar o ambiente completo.
docker run antes, pare-o (Ctrl+C).docker-compose: No terminal, na raiz do projeto, execute:
docker-compose up --build
up: Sobe os serviços definidos no arquivo.--build: Força a reconstrução da imagem da nossa aplicação (importante se você alterou o código).O Docker irá baixar a imagem do PostgreSQL, construir a imagem da sua API, criar uma rede para eles se comunicarem e iniciar os dois containers na ordem correta.
Parabéns! Você chegou ao final da nossa jornada!
Você não apenas construiu uma aplicação completa, mas também aprendeu a empacotá-la e distribuí-la usando as tecnologias mais requisitadas do mercado. Agora você tem uma aplicação:
O conhecimento adquirido ao longo destes 8 módulos forma a base sólida de um engenheiro de software completo. O próximo passo é pegar essa base e continuar construindo sobre ela, explorando novos desafios e tecnologias. O céu é o limite!