L. *_*Don 10 java maven docker
我正在处理一个具有 ~200MB 依赖项的项目,由于带宽有限,我想避免无用的上传。
当我推送我的 Dockerfile 时(我稍后会附加它),即使我没有触及 pom.xml,我也总是有大约 200MB 的上传:
FROM maven:3.6.0-jdk-8-slim
WORKDIR /app
ADD pom.xml /app
RUN mvn verify clean --fail-never
COPY ./src /app/src
RUN mvn package
ENV CONFIG_FOLDER=/app/config
ENV DATA_FOLDER=/app/data
ENV GOLDENS_FOLDER=/app/goldens
ENV DEBUG_FOLDER=/app/debug
WORKDIR target
CMD ["java","-jar","-Dlogs=/app/logs", "myProject.jar"]
Run Code Online (Sandbox Code Playgroud)
这个 Dockerfile 应该制作一个 200MB 的 fatJAR,包括所有的依赖项,这就是为什么每次都会发生 ~200MB 的上传。我想要实现的是构建一个包含所有依赖项的层,并“告诉”打包阶段不要将依赖项 JAR 包含到 fatJAR 中,而是在给定目录中搜索它们。
我想构建一个mvn dependency:copy-dependencies
在构建过程之前执行的脚本,然后将目录复制到容器中;然后构建一个“非胖”JAR,其中所有这些依赖项仅链接而不实际复制到其中。
这可能吗?
编辑:
我发现容器的 Maven 本地存储库位于/root/.m2
. 所以我结束了制作一个非常简单的脚本,如下所示:
构建Docker.sh
mvn verify -clean --fail-never
mv ~/.m2 ~/git/myProjectRepo/.m2
sudo docker build -t myName/myProject:"$1"
Run Code Online (Sandbox Code Playgroud)
并编辑Dockerfile,如:
# Use an official Python runtime as a parent image
FROM maven:3.6.0-jdk-8-slim
# Copy my Mavne Local Repository into the container thus creating a new layer
COPY ./.m2 /root/.m2
# Set the working directory to /app
WORKDIR /app
# Copy the pom.xml
ADD pom.xml /app
# Resolve and Download all dependencies: this will be done only if the pom.xml has any changes
RUN mvn verify clean --fail-never
# Copy source code and configs
COPY ./src /app/src
# create a ThinJAR
RUN mvn package
# Run the jar
...
Run Code Online (Sandbox Code Playgroud)
在构建过程之后,我声明/root/.m2
拥有所有目录,但是一旦我启动 JAR,我就会得到:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Priority
at myProject.ThreeMeans.calculate(ThreeMeans.java:17)
at myProject.ClusteringStartup.main(ClusteringStartup.java:7)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Priority
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 2 more
Run Code Online (Sandbox Code Playgroud)
也许我不应该通过它java -jar
?
如果我正确理解您想要实现的目标,问题是避免在每次 Docker 构建时创建一个包含所有 Maven 依赖项的胖 jar(以减轻重建后要推送的 Docker 层的大小)。
如果是,您可能对Spring Boot Thin Launcher感兴趣,它也适用于非 Spring-Boot 项目。README.md
相应的 GitHub 存储库中提供了一些综合文档:https :
//github.com/dsyer/spring-boot-thin-launcher#readme
总而言之,在您的 .js 文件中添加以下插件声明就足够了pom.xml
:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--<version>${spring-boot.version}</version>-->
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>1.0.19.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Run Code Online (Sandbox Code Playgroud)
理想情况下,此解决方案应与标准Dockerfile
设置相结合,以从 Docker 的缓存中受益(请参见下面的典型示例)。
Dockerfile
如果仅src/*
触及源代码文件 ( ) ,则避免在每次构建时重新下载所有 Maven 依赖项的原型在以下参考中给出:https :
//whitfin.io/speeding-up-maven-docker-builds/
更准确地说,建议Dockerfile
如下:
# our base build image
FROM maven:3.5-jdk-8 as maven
WORKDIR /app
# copy the Project Object Model file
COPY ./pom.xml ./pom.xml
# fetch all dependencies
RUN mvn dependency:go-offline -B
# copy your other files
COPY ./src ./src
# build for release
# NOTE: my-project-* should be replaced with the proper prefix
RUN mvn package && cp target/my-project-*.jar app.jar
# smaller, final base image
FROM openjdk:8u171-jre-alpine
# OPTIONAL: copy dependencies so the thin jar won't need to re-download them
# COPY --from=maven /root/.m2 /root/.m2
# set deployment directory
WORKDIR /app
# copy over the built artifact from the maven image
COPY --from=maven /app/app.jar ./app.jar
# set the startup command to run your binary
CMD ["java", "-jar", "/app/app.jar"]
Run Code Online (Sandbox Code Playgroud)
请注意,它依赖于Docker所谓的多阶段构建功能(存在两个FROM
指令),这意味着最终映像将比maven
基础映像本身小得多。
(如果您在开发阶段对该功能不感兴趣,可以删除行FROM openjdk:8u171-jre-alpine
和COPY --from=maven /app/app.jar ./app.jar
。)
在这种方法中,Maven 依赖项在行RUN mvn dependency:go-offline -B
之前获取COPY ./src ./src
(以从 Docker 的缓存中受益)。
但是请注意,dependency:go-offline
标准目标并不“完美”,因为一些动态依赖项/插件可能仍会在该mvn package
步骤触发一些重新下载。如果这对您来说是一个问题(例如,如果在某个时候您真的想离线工作),您可以查看其他SO 答案,该答案建议使用提供de.qaware.maven:go-offline-maven-plugin:resolve-dependencies
目标的专用插件。
在一般的 Dockerfile 容器构建中,按层工作,每次构建时这些层都可以在 catch 中使用,并且在没有更改的情况下使用。理想情况下它应该以同样的方式工作。
.m2
Maven 通常默认在位于 Ubuntu 用户主目录的文件夹中查找依赖项/home/username/
如果依赖的 jar 不可用,那么它将这些 jar 下载到 .m2 并使用它。
现在,您可以在 1 次成功构建后压缩并复制此.m2
文件夹,并将其移动到 Docker 容器用户的主目录中。
在运行构建命令之前执行此操作
注意:您可能需要替换.m2
docker 中的现有文件夹
所以你的 Docker 文件会是这样的
FROM maven:3.6.0-jdk-8-slim
WORKDIR /app
COPY .m2.zip /home/testuser/
ADD pom.xml /app
RUN mvn verify clean --fail-never
COPY ./src /app/src
RUN mvn package
...
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10831 次 |
最近记录: |