【发布时间】:2019-05-10 12:48:11
【问题描述】:
我正在开发一个具有约 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"]
这个 Dockerfile 应该创建一个 200MB 的 fatJAR,包括所有依赖项,这就是为什么每次都会上传 ~200MB 的原因。我想要实现的是构建一个包含所有依赖项的层,并“告诉”打包阶段不要将依赖项 JAR 包含到 fatJAR 中,而是在给定目录中搜索它们。
我想在构建过程之前构建一个执行mvn dependency:copy-dependencies的脚本,然后将目录复制到容器中;然后构建一个“非胖”JAR,所有这些依赖项仅链接而不实际复制到其中。
这可能吗?
编辑:
我发现容器的 Maven 本地存储库位于 /root/.m2 下。所以我结束了这样一个非常简单的脚本:
BuildDocker.sh
mvn verify -clean --fail-never
mv ~/.m2 ~/git/myProjectRepo/.m2
sudo docker build -t myName/myProject:"$1"
并编辑 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
...
在构建过程之后,我声明/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
也许我不应该通过java -jar 运行它?
【问题讨论】:
-
我个人没有用过这个,但也许 Jib 可以帮忙:github.com/GoogleContainerTools/jib
-
看看spring.io/blog/2018/11/08/spring-boot-in-a-container 它适用于 Spring Boot,但您可以对每个 maven 项目使用相同的方法。基本上你必须创建具有多个层的 Docker 文件,因此在构建过程中 Docker 可以缓存未更改的层。
-
在您编辑的问题中,您引入了类似于@MyTwoCents 建议的命令
COPY ./.m2 /root/.m2(因此可以将其视为执行RUN mvn dependency:go-offline -B的标准解决方案的替代方案,即使COPY ./.m2 /root/.m2更少便携,因为它需要在您的主机上安装 Maven),但我不确定这是否可以解决您关于与 fat jar 的推送相关的 ~200MB upload 的主要问题......cf .我的另一个comment