with jre jdk hub example create 8u121 java docker gradlew amazon-elastic-beanstalk

java - jre - Docker caché dependencias de gradle



dockerfile java jar (4)

Estoy tratando de implementar nuestra aplicación web java para aws elastic beanstalk usando la ventana acoplable, la idea es poder ejecutar el contenedor localmente para el desarrollo y las pruebas y eventualmente subirlo a producción utilizando git.

He creado una imagen base que tiene tomcat8 y java8, la imagen que realiza las compilaciones de gradle heredadas de esta imagen base, acelerando el proceso de compilación.

Todo funciona bien, excepto por el hecho de que el contenedor de aplicaciones heredado que se construye utilizando la ventana acoplable no parece almacenar en caché las dependencias de Gradle, sino que las descarga cada vez, incluido Gradlew. Construimos nuestra aplicación web usando el siguiente comando:

./gradlew war

¿Hay alguna manera de que pueda almacenar en caché los archivos en ~/.gradle esto aceleraría dramáticamente mi acumulación?

Esto no es tanto un problema en beanstalk, pero es un gran problema para los desarrolladores que intentan compilar y ejecutar localmente, ya que esto lleva mucho tiempo, como puedes imaginar.

El archivo de base de la imagen base:

FROM phusion/baseimage EXPOSE 8080 RUN apt-get update RUN add-apt-repository ppa:webupd8team/java RUN apt-get update RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections RUN apt-get -y install oracle-java8-installer RUN java -version ENV TOMCAT_VERSION 8.0.9 RUN wget --quiet --no-cookies http://archive.apache.org/dist/tomcat/tomcat-8/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz -O /tmp/catalina.tar.gz # Unpack RUN tar xzf /tmp/catalina.tar.gz -C /opt RUN mv /opt/apache-tomcat-${TOMCAT_VERSION} /opt/tomcat RUN ln -s /opt/tomcat/logs /var/log/tomcat RUN rm /tmp/catalina.tar.gz # Remove unneeded apps RUN rm -rf /opt/tomcat/webapps/examples RUN rm -rf /opt/tomcat/webapps/docs RUN rm -rf /opt/tomcat/webapps/ROOT ENV CATALINA_HOME /opt/tomcat ENV PATH $PATH:$CATALINA_HOME/bin ENV CATALINA_OPTS $PARAM1 # Start Tomcat CMD ["/opt/tomcat/bin/catalina.sh", "run"]

La aplicación dockerfile:

FROM <tag name here for base image> RUN mkdir ~/.gradle # run some extra stuff here to add things to gradle.properties file # Add project Source ADD . /var/app/myapp # Compile and Deploy Application, this is what is downloading gradlew and all the maven dependencies every time, if only there was a way to take the changes it makes to ~/.gradle and persist it as a cache layer RUN cd /var/app/myapp/ && ./gradlew war RUN mv /var/app/myapp/build/libs/myapp.war /opt/tomcat/webapps/ROOT.war # Start Tomcat CMD ["/opt/tomcat/bin/catalina.sh", "run"]


yo

Agregar la tarea resolviendo dependencias en build.gradle:

task resolveDependencies { doLast { project.rootProject.allprojects.each { subProject -> subProject.buildscript.configurations.each { configuration -> configuration.resolve() } subProject.configurations.each { configuration -> configuration.resolve() } } } }

y actualizar Dockerfile:

ADD build.gradle /opt/app/ WORKDIR /opt/app RUN gradle resolveDependencies ADD . . RUN gradle build -x test --parallel && / touch build/libs/api.jar

II

Bramido es lo que hago ahora:

construir.gradle

ext { speed = project.hasProperty(''speed'') ? project.getProperty(''speed'') : false offlineCompile = new File("$buildDir/output/lib") } dependencies { if (speed) { compile fileTree(dir: offlineCompile, include: ''*.jar'') } else { // ...dependencies } } task downloadRepos(type: Copy) { from configurations.all into offlineCompile }

Dockerfile

ADD build.gradle /opt/app/ WORKDIR /opt/app RUN gradle downloadRepos ADD . /opt/app RUN gradle build -Pspeed=true


Es posible que desee considerar dividir la imagen de su aplicación en dos imágenes: una para compilar myapp.war y la otra para ejecutar su aplicación. De esa manera, puede usar los volúmenes de la ~/.gradle acoplable durante la compilación real y vincular la carpeta ~/.gradle en el contenedor que realiza la compilación. Sin embargo, en lugar de un solo paso para ejecutar su aplicación, tendría más pasos. Ejemplo:

imagen del constructor

FROM <tag name here for base image including all build time dependencies> # Add project Source # -> you can use a project specific gradle.properties in your project root # in order to override global/user gradle.properties ADD . /var/app/myapp RUN mkdir -p /root/.gradle ENV HOME /root # declare shared volume path VOLUME /root/.gradle WORKDIR /var/app/myapp/ # Compile only CMD ["./gradlew", "war"]

imagen de la aplicación

FROM <tag name here for application base image> ADD ./ROOT.war /opt/tomcat/webapps/ROOT.war # Start Tomcat CMD ["/opt/tomcat/bin/catalina.sh", "run"]

Cómo usarlo en la raíz de su proyecto, asumiendo que el generador Dockerfile está ubicado allí y la aplicación Dockerfile está ubicada en la subcarpeta de la aplicación webapp (o en cualquier otra ruta que prefiera):

$ docker build -t builder . $ docker run --name=build-result -v ~/.gradle/:/root/.gradle/ builder $ docker cp build-result:/var/app/myapp/myapp.war webapp/ROOT.war $ cd webapp $ docker build -t application . $ docker run -d -P application

No he probado el código mostrado, pero espero que se te ocurra. El ejemplo podría incluso mejorarse utilizando volúmenes de datos para .gradle / cache, consulte la guía del usuario de Docker para obtener más información.


Me enfrenté a este problema. Como puede estar de acuerdo, es una buena práctica descargar las dependencias solo como un paso separado al construir la imagen de la ventana acoplable. Con Gradle se vuelve un poco complicado, ya que no hay soporte directo para descargar solo dependencias.

Opción 1: usar la imagen de docker-gradle Docker

Podemos usar una imagen de Gradle Docker pre-construida para construir la aplicación. Esto garantiza que no se trate de una compilación del sistema local sino de una compilación realizada en una imagen de ventana acoplable.

docker volume create --name gradle-cache docker run --rm -v gradle-cache:/home/gradle/.gradle -v "$PWD":/home/gradle/project -w /home/gradle/project gradle:4.7.0-jdk8-alpine gradle build ls -ltrh ./build/libs

  • gradle cache se carga aquí como un volumen. Así que las compilaciones posteriores reutilizarán las dependencias descargadas.
  • Después de esto, podríamos tener un Dockerfile para tomar este artefacto y generar una imagen específica de la aplicación para ejecutar la aplicación.
  • De esta manera, la imagen del constructor no es necesaria. El flujo de compilación de la aplicación y el flujo de ejecución de la aplicación están separados.
  • Dado que el volumen de caché gradle está montado, podríamos reutilizar las dependencias descargadas en diferentes proyectos gradle.

Opción 2: construcción de varias etapas

----- Dockerfile -----

FROM openjdk:8 AS TEMP_BUILD_IMAGE ENV APP_HOME=/usr/app/ WORKDIR $APP_HOME COPY build.gradle settings.gradle gradlew $APP_HOME COPY gradle $APP_HOME/gradle RUN ./gradlew build || return 0 COPY . . RUN ./gradlew build FROM openjdk:8 ENV ARTIFACT_NAME=your-application.jar ENV APP_HOME=/usr/app/ WORKDIR $APP_HOME COPY --from=TEMP_BUILD_IMAGE $APP_HOME/build/libs/$ARTIFACT_NAME . EXPOSE 8080 CMD ["java","-jar",$ARTIFACT_NAME]

En el anterior Dockerfile

  • Primero intentamos copiar los archivos de gradle del proyecto solo, como build.gradle, gradlew, etc.
  • Luego copiamos el propio directorio de Gradle.
  • Y luego intentamos ejecutar el build. En este punto, no hay otros archivos de código fuente en el directorio. Así que la construcción fallará. Pero antes de eso se descargarán las dependencias.
  • Como esperamos que la compilación falle, he probado una técnica simple para devolver 0 y permitir que la ventana acoplable continúe ejecutándose
  • esto acelerará los flujos de compilación subsiguientes, ya que todas las dependencias se descargan y la ventana acoplable almacena en caché esta capa. Comparativamente, el montaje en volumen del directorio de caché de Gradle sigue siendo el mejor enfoque.
  • El ejemplo anterior también muestra la creación de imágenes de la ventana acoplable en varias etapas , lo que evita múltiples archivos de compilación de la ventana acoplable.

intenta cambiar el directorio de inicio de usuario de Gradle

EJECUTAR mkdir -p /opt/gradle/.gradle
ENV GRADLE_USER_HOME = / opt / gradle / .gradle