plugin mvn hub application java maven docker dockerfile

java - hub - mvn package docker build



Dependencias de caché de docker de Maven (6)

Estoy tratando de usar la ventana acoplable para automatizar las construcciones de Maven. El proyecto que quiero construir demora casi 20 minutos en descargar todas las dependencias, así que intenté crear una imagen de ventana acoplable que almacene en caché estas dependencias, pero parece que no las guarda. Mi Dockerfile es

FROM maven:alpine RUN mkdir -p /usr/src/app WORKDIR /usr/src/app ADD pom.xml /usr/src/app RUN mvn dependency:go-offline

La imagen se construye, y descarga todo. Sin embargo, la imagen resultante es del mismo tamaño que la imagen básica de maven:alpine , por lo que no parece haber guardado en caché las dependencias de la imagen. Cuando trato de usar la imagen para mvn compile , pasa por los 20 minutos completos de volver a descargar todo.

¿Es posible crear una imagen de Maven que almacene en caché mis dependencias para que no tengan que descargarse cada vez que uso la imagen para realizar una compilación?

Estoy ejecutando los siguientes comandos:

docker build -t my-maven . docker run -it --rm --name my-maven-project -v "$PWD":/usr/src/mymaven -w /usr/src/mymaven my-maven mvn compile

Entiendo que todo lo que haga RUN durante el proceso de construcción de la ventana acoplable se convierte en parte de la imagen resultante.


@Kim es el más cercano, pero aún no está del todo allí. No creo que agregar --fail-never sea ​​correcto, incluso si se hace el trabajo.

El comando de verify hace que se ejecuten muchos complementos, lo cual es un problema (para mí). No creo que deban ejecutarse cuando lo único que quiero es instalar dependencias. También tengo una compilación de varios módulos y una subcompilación de javascript, lo que complica aún más la configuración.

Pero ejecutar solo verify no es suficiente, porque si ejecuta la install en los siguientes comandos, se usarán más complementos, lo que significa más dependencias para descargar. Maven se niega a descargarlos de lo contrario. Lectura relevante: Maven: Introducción al ciclo de vida de la compilación

Básicamente, tienes que encontrar qué propiedades deshabilitan cada complemento y agregarlas una por una, para que no rompan tu compilación.

WORKDIR /srv # cache Maven dependencies ADD cli/pom.xml /srv/cli/ ADD core/pom.xml /srv/core/ ADD parent/pom.xml /srv/parent/ ADD rest-api/pom.xml /srv/rest-api/ ADD web-admin/pom.xml /srv/web-admin/ ADD pom.xml /srv/ RUN mvn -B clean install -DskipTests -Dcheckstyle.skip -Dasciidoctor.skip -Djacoco.skip -Dmaven.gitcommitid.skip -Dspring-boot.repackage.skip -Dmaven.exec.skip=true -Dmaven.install.skip -Dmaven.resources.skip # cache YARN dependencies ADD ./web-admin/package.json ./web-admin/yarn.lock /srv/web-admin/ RUN yarn --non-interactive --frozen-lockfile --no-progress --cwd /srv/web-admin install # build the project ADD . /srv RUN mvn -B clean install

pero algunos complementos no son tan fáciles de omitir. No soy un experto en maven (así que no sé por qué ignora la opción cli; podría ser un error), pero lo siguiente funciona como se espera para org.codehaus.mojo:exec-maven-plugin

<project> <properties> <maven.exec.skip>false</maven.exec.skip> </properties> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.3.2</version> <executions> <execution> <id>yarn install</id> <goals> <goal>exec</goal> </goals> <phase>initialize</phase> <configuration> <executable>yarn</executable> <arguments> <argument>install</argument> </arguments> <skip>${maven.exec.skip}</skip> </configuration> </execution> <execution> <id>yarn run build</id> <goals> <goal>exec</goal> </goals> <phase>compile</phase> <configuration> <executable>yarn</executable> <arguments> <argument>run</argument> <argument>build</argument> </arguments> <skip>${maven.exec.skip}</skip> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>

tenga en cuenta el <skip>${maven.exec.skip}</skip> explícito - otros complementos lo seleccionan de los parámetros de cli pero no este (ni -Dmaven.exec.skip=true ni -Dexec.skip=true trabajar por sí mismo)

Espero que esto ayude


Por lo general, no hay cambios en el archivo pom.xml , pero otros cambios en el código src cuando se intenta iniciar la compilación de imágenes de la ventana acoplable. En tal circunstancia puedes hacer esto:

Para tu información:

FROM registry.cn-hangzhou.aliyuncs.com/acs/maven:3-jdk-8 MAINTAINER Eric Kim <[email protected]> ENV PITBULL_EUREKA=/usr/src/app RUN mkdir -p $PITBULL_EUREKA WORKDIR $PITBULL_EUREKA # add pom.xml only here, and download dependency ADD pom.xml $PITBULL_EUREKA RUN ["/usr/local/bin/mvn-entrypoint.sh", "mvn", "verify", "clean", "--fail-never"] # now we can add all source code and start compiling ADD . $PITBULL_EUREKA RUN ["mvn", "package"] EXPOSE 8888 CMD ["java", "-jar", "./target/eureka-0.0.1-SNAPSHOT.jar"]

Así que la clave es:

  1. agregar el archivo pom.xml

  2. luego mvn verify --fail-never it, se descargarán las dependencias de maven.

  3. a continuación, agregue todo su archivo fuente e inicie su compilación ( mvn package ).

Cuando hay cambios en su pom.xml o está ejecutando este script por primera vez, la ventana acoplable hará 1 -> 2 -> 3. Cuando no hay cambios en el archivo pom.xml , la ventana acoplable saltará el paso 1、2 y hacer 3 directamente.

Este truco simple puede usarse en muchas otras circunstancias de administración de paquetes.


Resulta que la imagen que estoy usando como base tiene una imagen principal que define

VOLUME "$USER_HOME_DIR/.m2"

consulte: https://github.com/carlossg/docker-maven/blob/322d0dff5d0531ccaf47bf49338cb3e294fd66c8/jdk-8/Dockerfile

El resultado es que durante la compilación, todos los archivos se escriben en $USER_HOME_DIR/.m2 , pero debido a que se espera que sea un volumen, ninguno de esos archivos se conserva en la imagen del contenedor.

Actualmente, en Docker no hay forma de anular el registro de esa definición de volumen, por lo que sería necesario crear una imagen de experto por separado, en lugar de utilizar la imagen de experto oficial.


Si las dependencias se descargan después de que el contenedor ya está activo, entonces debe confirmar los cambios en este contenedor y crear una nueva imagen con los artefactos descargados.


Similar a la respuesta @Kim pero uso dependency:resolve comando mvn. Así que aquí está mi completo Dockerfile:

FROM maven:3.5.0-jdk-8-alpine WORKDIR /usr/src/app # First copy only the pom file. This is the file with less change COPY ./pom.xml . # Download the package and make it cached in docker image RUN mvn -B -f ./pom.xml -s /usr/share/maven/ref/settings-docker.xml dependency:resolve # Copy the actual code COPY ./ . # Then build the code RUN mvn -B -f ./pom.xml -s /usr/share/maven/ref/settings-docker.xml package # The rest is same as usual EXPOSE 8888 CMD ["java", "-jar", "./target/YOUR-APP.jar"]


Tuve este problema sólo un poco hace tiempo. Hay muchas soluciones en la web, pero la que funcionó para mí es simplemente montar un volumen para el directorio de módulos de Maven:

mkdir /opt/myvolumes/m2

luego en el Dockerfile:

... VOLUME /opt/myvolumes/m2:/root/.m2 ...

Hay mejores soluciones, pero no tan sencillas.

Esta publicación del blog hace un esfuerzo adicional para ayudarte a almacenar en caché todo:

https://keyholesoftware.com/2015/01/05/caching-for-maven-docker-builds/