Dockerfile para Imagen por capas Spring Boot
creando Spring-Boot por capas en una imagen docker con Dockerfile
Table of contents
Una recomendación a la hora de realizar imagenes Docker de aplicaciones spring-boot es empaquetar la aplicación por capas.
Al crear nuestras imagenes por capas evitamos tener construciones y empaquetados pesados como lo son los jar, adiconal a esto ganamos tiempo de compilación, ya que podemos reutilizar las capas que no sufrieron cambios y usar solo las capas afectadas por nuestros cambios.
Configuración
Lo primero es incluir en el plugin spring-boot-maven-plugin
la configuración de capas.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>
Creando el Dockerfile
Para lograr obtener las capas de nuestra aplicación empaquetada en un jar debemos debemos ejecutar java -Djarmode=layertools -jar app.jar extract
esto extraera las capas de spring boot.
Spring boot tiene la siguiente estructura para sus capas:
- dependencies
- spring-boot-loader
- snapshot-dependencies
- application
Para hacer esta extración en el Dockerfile
vamos a crear una sección que denominaremos builder
y en esta ejecutamos la sentencia de extracción.
# the first stage of our build will extract the layers
FROM openjdk:14-ea-jdk-alpine as builder
ARG WORKDIR_BASE=/home/application
WORKDIR $WORKDIR_BASE/bin
COPY ./target/my-app.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract
Al final de la sección vemos la sentencia escencial para extracer las capas RUN java -Djarmode=layertools -jar app.jar extract
Luego en una nueva sección vamos a generar nuestra aplicación con la configuración de variables de entorno y demas elementos que permitirán que esta funcione correctamente.
Nos quedaría algo como esto
## Builder App Image
FROM openjdk:14-ea-jdk-alpine
LABEL maintainer="Henry Martinez (hmartinez@novopayment.com)"
ARG USER_GROUP=app-group
ARG USER=app-user
ARG WORKDIR_BASE=/home/application
WORKDIR $WORKDIR_BASE/bin
RUN mkdir -p $WORKDIR_BASE/logs && addgroup $USER_GROUP && adduser \
--disabled-password \
--gecos "" \
--ingroup $USER_GROUP \
--no-create-home \
$USER
EXPOSE 8080
ENV TZ="America/Bogota"
COPY --from=builder $WORKDIR_BASE/bin/dependencies ./
RUN true
COPY --from=builder $WORKDIR_BASE/bin/spring-boot-loader ./
RUN true
COPY --from=builder $WORKDIR_BASE/bin/snapshot-dependencies ./
RUN true
COPY --from=builder $WORKDIR_BASE/bin/application ./
RUN chown -R $USER:$USER_GROUP $WORKDIR_BASE
USER $USER
ENTRYPOINT java org.springframework.boot.loader.JarLauncher
De lo anterior, las lineas que debemos resaltar son las que incluyen las capas de spring boot en nuestra aplicación
COPY --from=builder $WORKDIR_BASE/bin/dependencies ./
RUN true
COPY --from=builder $WORKDIR_BASE/bin/spring-boot-loader ./
RUN true
COPY --from=builder $WORKDIR_BASE/bin/snapshot-dependencies ./
RUN true
COPY --from=builder $WORKDIR_BASE/bin/application ./
y la linea de ejecución de la aplicación ENTRYPOINT java org.springframework.boot.loader.JarLauncher
Estas dos secciones son la que nos permiten construir y ejecutar nuestra aplicacion por capas.
Ya con esto tendriamos nuestro Dockerfile finalizado para crear y ejecutar una aplicación con spring boot en capas, solo nos resta construir la imagen que se ejecuta con el comando
docker build -t my-app:latest .
my-app:latest
es el nombre con el que deseamos que la imagen se cree.