Introdução: por que o Docker é importante para o desenvolvedor Java?
O desenvolvimento Java moderno raramente dispensa a conteinerização. O Docker permite empacotar a aplicação junto com todas as dependências, JVM e configuração em um contêiner isolado. Isso resolve o problema de "funciona na minha máquina" e simplifica o CI/CD. Neste artigo, abordaremos o ciclo completo: desde a instalação do Docker até a otimização de imagens para produção.
1. Fundamentos do Docker para Java
1.1 O que é Docker e por que ele é útil para projetos Java?
Docker é uma plataforma para criar, distribuir e executar aplicações em contêineres. Para Java, isso é especialmente relevante:
- Isolamento de versões da JVM — é possível usar Java 11 para um serviço e Java 17 para outro no mesmo host.
- Reprodutibilidade — a imagem contém a versão exata do JDK, bibliotecas e utilitários do sistema.
- Escalabilidade — é fácil executar várias instâncias via Kubernetes ou Docker Swarm.
1.2 Instalação do Docker
Para começar, instale o Docker Desktop (Windows/Mac) ou o Docker Engine (Linux). Verifique a instalação:
docker --versiondocker info2. Criando um Dockerfile para uma aplicação Java
Vamos considerar uma aplicação Spring Boot simples. Crie um arquivo Dockerfile na raiz do projeto.
2.1 Dockerfile básico
# Usamos a imagem oficial do OpenJDKFROM openjdk:17-jdk-alpine
# Definimos o diretório de trabalhoWORKDIR /app
# Copiamos o arquivo JARCOPY target/myapp.jar app.jar
# Abrimos a portaEXPOSE 8080
# Comando de inicializaçãoENTRYPOINT ["java", "-jar", "app.jar"]2.2 Construção e execução do contêiner
# Construção da imagemdocker build -t my-java-app .
# Execução do contêinerdocker run -p 8080:8080 my-java-appApós a execução, a aplicação estará disponível em http://localhost:8080.
3. Otimização de imagens Docker para Java
Imagens grandes retardam a implantação. Vamos considerar as principais técnicas de otimização.
3.1 Construção em múltiplos estágios (Multi-stage builds)
Permite separar a etapa de construção da etapa de execução. Apenas o JAR entra na imagem final, sem Maven/Gradle e fontes.
# Estágio de construçãoFROM maven:3.8.5-openjdk-17 AS buildWORKDIR /appCOPY pom.xml .RUN mvn dependency:go-offlineCOPY src ./srcRUN mvn package -DskipTests
# Estágio de execuçãoFROM openjdk:17-jdk-alpineWORKDIR /appCOPY --from=build /app/target/myapp.jar app.jarEXPOSE 8080ENTRYPOINT ["java", "-jar", "app.jar"]3.2 Otimização de camadas
O Docker armazena em cache as camadas. Separe a cópia dos dados: primeiro as dependências (mudam raramente), depois o código (muda com frequência).
FROM maven:3.8.5-openjdk-17 AS buildWORKDIR /app# Copiamos apenas o POM e baixamos as dependênciasCOPY pom.xml .RUN mvn dependency:go-offline# Copiamos as fontes e construímosCOPY src ./srcRUN mvn package -DskipTests
FROM openjdk:17-jdk-alpineWORKDIR /appCOPY --from=build /app/target/*.jar app.jarEXPOSE 8080ENTRYPOINT ["java", "-jar", "app.jar"]3.3 Usando jlink para criar uma JRE mínima
Se você usa Java 9+, pode criar uma JRE personalizada apenas com os módulos necessários.
FROM openjdk:17-slim AS jre-buildRUN jlink --add-modules java.base,java.logging,java.sql \ --output /jre \ --strip-debug \ --no-man-pages \ --no-header-files
FROM alpine:latestCOPY --from=jre-build /jre /jreCOPY target/app.jar /app.jarENTRYPOINT ["/jre/bin/java", "-jar", "/app.jar"]Essa imagem pode pesar menos de 50 MB em vez de 300+ MB.
4. Docker Compose para microsserviços Java
Se você tem vários serviços (por exemplo, Spring Boot + PostgreSQL), use docker-compose.yml.