我想加快速度。
场景是这样的:
- 触摸/更改一些源代码
-
docker build
- Maven下载世界
- Maven编译我的项目
-
docker run
- 触摸/更改一些源代码
-
docker build
- Maven下载世界
- Maven编译我的项目
-
docker run
- 触摸/更改一些源代码
-
docker build
- Maven下载世界
- Maven编译我的项目
-
docker run
- …
maven下载世界
让我们继续前进,让我的情况有所好转。 为了说明起见,我们将从这个通用的原型创建的骨架项目开始:
package com.keyholesoftware.blog;
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
package com.keyholesoftware.blog;
import junit.framework.*;
public class AppTest extends TestCase
{
public void testApp()
{
assertTrue( true );
}
}
FROM maven:3.2.5-jdk-8u40
RUN mkdir --parents /usr/src/app
WORKDIR /usr/src/app
ADD . /usr/src/app
RUN mvn verify
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.keyholesoftware.blog</groupId>
<artifactId>khs-docker-caching-blog</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
当我进行背对背构建时,情况还不错。
$ docker build .
...
$ docker build .
...
请注意,由于所有内容都已缓存,因此第二个构建速度很快。 但是当我们做这样的事情呢:
$ docker build .
...
$ touch src/main/java/com/keyholesoftware/blog/App.java
...
$ docker build .
...
请注意,重新下载部分不必要地减慢了第二个构建的速度。
我围坐在一旁,绝望了一段时间,直到我想起了选择性缓存的技巧:
FROM maven:3.2.5-jdk-8u40
RUN mkdir --parents /usr/src/app
WORKDIR /usr/src/app
# selectively add the POM file
ADD pom.xml /usr/src/app/
# get all the downloads out of the way
RUN mvn verify clean --fail-never
ADD . /usr/src/app
RUN mvn verify
让我们再次尝试该顺序。
$ docker build .
...
$ touch src/main/java/com/keyholesoftware/blog/App.java
...
$ docker build .
...
越来越好,但是在第二个版本中仍然有一些下载。 它们与surefire测试/插件相关。 实际上,此过程将帮助我们消除动态选择的下载并将其锁定。 在这种情况下,我们将锁定surefire提供程序。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.keyholesoftware.blog</groupId>
<artifactId>khs-docker-caching-blog</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<surefire.version>2.8.1</surefire.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<!-- lock down our surefire provider -->
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit3</artifactId>
<version>${surefire.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
让我们再次尝试该顺序。
$ docker build .
...
$ touch src/main/java/com/keyholesoftware/blog/App.java
...
$ docker build .
...
因此,现在,除非我们更改POM,否则不必重新下载任何内容。 真好
现在的场景是这样的:
- 触摸/更改一些源代码
-
docker build
- Maven下载世界
- Maven编译我的项目
-
docker run
- 触摸/更改一些源代码
-
docker build
- Maven编译我的项目
-
docker run
- 触摸/更改一些源代码
-
docker build
- Maven编译我的项目
-
docker run
- …
注意,“ maven下载世界 ”步骤仅发生一次(当然,除非我实际上更改了POM)。
最后的想法
也许有更好的方法来处理其中的某些问题(例如,dependency:resolve / resolve-plugin,但似乎无法完全解决问题,并且可能与图有关),但我主要想强调一下选择性添加的可能用途。 /缓存。
其他说明:
- 对于您Ruby + Rakefile,Python + requirements.txt,Node + package.json,Go + GoDeps.json等。伙计们-Maven没有明确的“安装依赖项”步骤。 如果您觉得无聊,请参阅《构建生命周期简介》 。
- 对于您的Gradle员工,我用的不多。 你怎么看?
谢谢阅读!