miércoles, 26 de agosto de 2020

Optimizar MultiStage build en Docker y Maven

 En esta entrada les quiero presentar un truco pequeño sobre como optimizar sus builds en Docker y Maven con tan solo cambiar una linea de código. 

Ya es bien sabido que Docker se ha convertido en una herramienta básica para los desarrolladores al momento de distribuir sus aplicaciones. Los contenedores de docker pueden ser descargados y ejecutados en cualquier ambiente compatible y ademas es uno de los manéjadores de contenedores soportados por kubernetes que se ha vuelto el estándar para correr aplicaciones en la nube. 

No solo eso. Con el soporte de multi-stage builds en Docker es posible támbien simplificar la manera en que las aplicaciones son compiladas y empaquetadas antes de ser distribuidas en su contenedor final. En un build multi-stage docker prepara un contenedor donde se ejecutan algunas instrucciones de compilado / pruebas y el resultado final es copiado a un nuevo contenedor.

Con esto se simplifica la manera en la que nuevos desarrolladores o servidores CI compilan las aplicaciones. Solo es necesario tener docker y poder descargar un contenedor con todas las herramientas ya listas para la compilación. Es este articulo lo haremos con maven. 

Un ejemplo de un multi-stage build con maven y docker, y que ademas se encuentra mucho en proyectos de github, se puede estructurar como sigue.

FROM maven:3.6-jdk-11 as build
WORKDIR /src
ADD * /src
RUN mvn package -DskipTests

FROM adoptopenjdk:11-jre-hotspot
COPY --from=build /src/target/app.jar /app/app.jar
CMD ["java", "-jar", "/app/app.jar"]
EXPOSE 8080

Este método es muy común. Simplemente descargamos un contenedor docker que cuente con maven y java. Luego agregamos todo el proyecto completo al directorio src y empaquetamos el proyecto.

Luego tomamos un nuevo contenedor que sera encargado de correr nuestra aplicación. Copiamos el jar final desde el contenedor con alias build y lo colocamos en nuestro contenedor final con propiedades extra para poder correr nuestra aplicación. 


Como optimizar este build? 

El build se puede optimizar con solo agregar dos lineas de código en nuestro Dockerfile. Lo primero sera copiar el archivo pom.xml por sí solo y correr mvn package. 
Esto instruye a docker a correr un build de maven, descargar todas las dependencias y crear una capa en el cache de docker con todas las dependencias.
El archivo se ve como sigue.
FROM maven:3.6-jdk-11 as build

WORKDIR /src
ADD pom.xml .
RUN mvn package -DskipTests
# Este paso optimiza los builds hasta que el archivo pom o las dependencias cambien
ADD src src
RUN mvn package -DskipTests

FROM adoptopenjdk:11-jre-hotspot
COPY --from=build /src/target/app.jar /app/app.jar
CMD ["java", "-jar", "/app/app.jar"]
EXPOSE 8080

Una vez que esta capa este en el cache de docker. Cualquier build que siga y comparta él mismo cache ya no necesitara descargar todas las dependencias y solo se enfocara en compilar los archivos dentro del directorio src. 


Espero y este pequeño truco les sirva para optimizar sus proyectos que utilizan maven y docker