1. 程式人生 > >Maven Docker映象使用技巧

Maven Docker映象使用技巧

14808592379396

Maven是目前最流行的Java專案管理工具之一,提供了強大的包依賴管理和應用構建功能。

Docker提供了官方的Maven映象可以用於管理和構建Java應用。與直接安裝使用Maven工具相比,使用Docker映象具有更好的可移植性,可以方便地進行版本切換,非常適合在持續整合過程中使用。

關於Maven官方映象的用法可以參考使用文件

使用阿里雲加速

Maven官方倉庫在國內網路下的下載速度實在是讓人慾哭無淚,利用阿里雲的Maven映象可以大大提升軟體包下載速度。

它的配置檔案settings.xml如下

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      https://maven.apache.org/xsd/settings-1.0.0.xsd">
  <localRepository>/usr/share/maven/ref/repository</localRepository>
  <mirrors>
    <mirror>
        <!--This sends everything else to /public -->
        <id>aliyun-nexus</id>
        <mirrorOf>*</mirrorOf> 
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    </mirror>
    <mirror>
        <!--This is used to direct the public snapshots repo in the 
            profile below over to a different nexus group -->
        <id>aliyun-nexus-public-snapshots</id>
        <mirrorOf>public-snapshots</mirrorOf> 
        <url>http://maven.aliyun.com/nexus/content/repositories/snapshots/</url>
      </mirror>
    </mirrors>
</settings>

阿里雲容器服務提供了預構建的Docker映象可供直接使用registry.cn-hangzhou.aliyuncs.com/acs/maven

我們可以像使用mvn命令一樣,直接在當前目錄中執行如下命令來構建應用

docker run -it --rm --name maven -v "$(pwd)":/usr/src/app -w /usr/src/app registry.cn-hangzhou.aliyuncs.com/acs/maven mvn clean install

如果希望能夠快取下載的maven倉庫,我們可以利用Docker的檔案捲來實現

首先執行如下命令建立一個名為“maven-repo”的檔案卷

docker volume create --name maven-repo

在之後的呼叫中,將其掛載到maven映象中倉庫下載目錄上

docker run -it --rm --name maven -v "$(pwd)":/usr/src/app -v maven-repo:/usr/share/maven/ref -w /usr/src/app registry.cn-hangzhou.aliyuncs.com/acs/maven mvn clean install

這樣maven倉庫就不會每次都下載一遍了。

優化Dockerfile提升構建速度

我們可以在Dockerfile中構建應用,並利用Docker構建時的分層快取機制來提升構建速度

下面是一個示例Dockerfile.build檔案

FROM registry.cn-hangzhou.aliyuncs.com/acs/maven:3-jdk-8

ENV MY_HOME=/app
RUN mkdir -p $MY_HOME
WORKDIR $MY_HOME
ADD pom.xml $MY_HOME

# get all the downloads out of the way
RUN ["/usr/local/bin/mvn-entrypoint.sh","mvn","verify","clean","--fail-never"]

# add source
ADD . $MY_HOME

# run maven verify
RUN ["/usr/local/bin/mvn-entrypoint.sh","mvn","verify"]

其中的一個重要技巧就是先把pom.xml新增到工作目錄,利用maven命令下載應用所需jar包之後,再新增應用原始檔進行編譯。這樣只要pom.xml沒有更新就不會重新下載所依賴的jar包,可以大大加快映象構建速度。

我們可以通過如下命令來編譯應用

docker build -t builder-img -f Dockerfile.build .

我們還可以將構建出來的 .jar 檔案從Docker映象中拷貝到本地

docker create --name builder builder-img
docker cp builder:/app/target ./target

應用編譯與Docker映象構建分離

對於靜態編譯型語言,我們通常需要將應用編譯過程與映象構建過程分離。主要有以下兩個考慮:

  • 最終生成的Docker映象不應該包含原始碼 - 資訊保安
  • 最終生成的Docker映象應該最小化,不應該包含編譯時工具 - 加速應用交付,減小攻擊面

傳統做法是通過一個單獨的Dockerfile來構建應用,並將編譯結果從Docker映象中拷貝出來。而在Docker 17.05版本之後,Docker引入了多階段構建方式,我們可以把映象構建分解為若干個部分,如下所示

  1. 第一階段負責編譯 Java 應用
  2. 第一階段利用最小化的 JRE 映象 openjdk:8-jre-alpine 來構建應用容器映象
# First stage - Compiling application
FROM registry.cn-hangzhou.aliyuncs.com/acs/maven:3-jdk-8 AS build-env

ENV MY_HOME=/app
RUN mkdir -p $MY_HOME
WORKDIR $MY_HOME
ADD pom.xml $MY_HOME

# get all the downloads out of the way
RUN ["/usr/local/bin/mvn-entrypoint.sh","mvn","verify","clean","--fail-never"]

# add source
ADD . $MY_HOME

# run maven verify
RUN ["/usr/local/bin/mvn-entrypoint.sh","mvn","verify"]

# Second stage - build image
FROM openjdk:8-jre-alpine

COPY --from=build-env /app/target/*.jar /app.jar

ENV JAVA_OPTS=""
ENV SERVER_PORT 8080

EXPOSE ${SERVER_PORT}

ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/urandom -jar /app.jar" ]

通過這個方法可以將,700多兆的Docker映象,縮小到100兆,這是巨大的節約。

總結

本文以Maven為例介紹了Docker在應用構建中的一些常見技巧