Dockerfile Multi-Stage optimizado para Spring Boot y JVM
Una imagen de contenedor para Java nunca debe incluir Maven ni el código fuente en la imagen final. Se usa una fase de build (con Maven/Gradle y JDK completo) y una fase de ejecución (con JRE mínimo tipo Eclipse Temurin / BellSoft Liberica Alpine/Distroless). Se extraen las capas del jar con layertools (java -Djarmode=layertools -jar app.jar extract) para aprovechar la caché de capas de Docker.
En una línea FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/application/ ./
ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-XX:MaxRAMPercentage=75.0", "org.springframework.boot.loader.launch.JarLauncher"]
# Imagen OCI sin Dockerfile (requiere Docker en local)
./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=registry.acme.com/taskflow:1.4.0
# Con Jib: construye y publica sin demonio de Docker
./mvnw com.google.cloud.tools:jib-maven-plugin:build -Dimage=registry.acme.com/taskflow:1.4.0
# CDS con Spring Boot 3.3+ (en el Dockerfile, tras extraer el JAR)
java -XX:ArchiveClassesAtExit=app.jsa -Dspring.context.exit=onRefresh -jar app.jar # entrenamiento
java -XX:SharedArchiveFile=app.jsa -jar app.jar # arranques posteriores
# Inspeccionar capas y vulnerabilidades
dive registry.acme.com/taskflow:1.4.0
trivy image registry.acme.com/taskflow:1.4.0
Cómo funciona por dentro
Además del Dockerfile multi-etapa escrito a mano (día 15), hay dos alternativas sin Dockerfile. Cloud Native Buildpacks, integrados en Spring Boot con ./mvnw spring-boot:build-image, detectan la aplicación, eligen un JRE, crean capas optimizadas, configuran la memoria de la JVM y generan una imagen reproducible con usuario sin privilegios. Jib, de Google, construye y sube la imagen directamente desde Maven sin necesitar Docker.
Para el arranque, Spring Boot 3.3 facilita usar CDS (Class Data Sharing): en un primer arranque de entrenamiento la JVM vuelca un archivo con las clases ya analizadas, y los siguientes arranques lo reutilizan, recortando el tiempo de arranque de forma notable. Las imágenes nativas con GraalVM arrancan en milisegundos a cambio de un build mucho más lento y algunas restricciones de reflexión.
Sea cual sea la vía, comprueba el resultado: tamaño, usuario, capas (con la herramienta dive) y vulnerabilidades (Trivy, Grype).
mvn spring-boot:run dentro del contenedor en producción, dejando el JDK y herramientas de compilación expuestas.
Se conecta con Docker LayersAlpine / DistrolessSpring Boot Layertools