Construir una aplicación Java
Un servicio Java no necesita un JDK completo para ejecutarse, solo un JRE. Así que construye el jar con el conjunto de herramientas en una etapa y luego ejecútalo sobre la base ligera jre en la siguiente. El compilador, la herramienta de construcción y la caché de dependencias se quedan en la etapa de construcción, y la imagen final lleva el runtime y tu jar.
Estas construyen sobre ghcr.io/quenchworks/images/maven:3.9 o ghcr.io/quenchworks/images/gradle:9, y luego se ejecutan sobre ghcr.io/quenchworks/images/jre:21. Haz coincidir la línea del JRE con la versión de Java para la que compilaste.
El Dockerfile multi-etapa
# Build stage: resolve dependencies, then package the jar.FROM ghcr.io/quenchworks/images/maven:3.9 AS buildWORKDIR /app
# Resolve dependencies first so the layer caches when only code changes.COPY pom.xml ./RUN ["mvn", "-B", "dependency:go-offline"]COPY src ./srcRUN ["mvn", "-B", "-o", "package", "-DskipTests"]
# Runtime stage: run the jar on the slim JRE base, nonroot.FROM ghcr.io/quenchworks/images/jre:21 AS runtimeWORKDIR /appCOPY --from=build /app/target/*.jar /app/app.jarUSER 1001EXPOSE 8080ENTRYPOINT ["java", "-jar", "/app/app.jar"]# Build stage: build the jar with Gradle.FROM ghcr.io/quenchworks/images/gradle:9 AS buildWORKDIR /app
# Cache dependencies before copying the full source.COPY build.gradle.kts settings.gradle.kts ./RUN ["gradle", "dependencies", "--no-daemon"]COPY src ./srcRUN ["gradle", "bootJar", "--no-daemon", "-x", "test"]
FROM ghcr.io/quenchworks/images/jre:21 AS runtimeWORKDIR /appCOPY --from=build /app/build/libs/*.jar /app/app.jarUSER 1001EXPOSE 8080ENTRYPOINT ["java", "-jar", "/app/app.jar"]Qué hace cada etapa
- Construcción. La imagen
mavenogradlelleva el JDK y la herramienta de construcción. Resuelve las dependencias antes de copiar el código fuente para que esa capa se cachee entre construcciones, y luego empaqueta el jar. La caché de dependencias y el compilador se quedan en esta etapa. - Runtime. Empieza desde
jre:21, copia el único jar, baja auid 1001y ejecútalo. Sin JDK, sin herramienta de construcción, sin código fuente.
Siguiente
- Construir un jar autocontenido (Spring Boot, Quarkus, un jar empaquetado) mantiene la etapa de runtime en un único
COPY; las disposiciones de varios jars también funcionan, basta con copiar las capas de dependencias y de la aplicación. - Fija por digest para que cada construcción ejecute exactamente la base que se escaneó y firmó.