[Docker]構建maven鏡像並用鏡像打包
寫在前面
由於項目使用的maven版本較低,在DockerHub上沒有可以直接使用的maven鏡像,於是自己構建了maven鏡像,並使用該鏡像將項目工程打包。
爲什麼要構建maven鏡像呢?有了maven鏡像之後,就不需要再在新的開發環境中安裝maven了。鏡像中的maven版本固定,不會出現不同開發者使用不同版本maven打包出現不必要的問題。
構建過程和maven打包過程有一些需要注意的地方,記錄備查。
構建maven鏡像
在前一篇博文中記錄了構建java8的過程。構建maven鏡像依賴於之前構建的java環境。簡而言之,就是先啓動一個java8的docker,然後在這個docker實例中安裝maven、配置環境變量、構建成鏡像,提交到私有registry。以後打包直接一句指令就可以啦。
docker實例中安裝maven
這一步跟在linux中安裝maven過程類似,簡略說一下。注意哦,以下是正常的安裝maven的步驟。但是在docker環境下會啓動maven有問題。先記下,後文講問題及我的解決方法。
- 假設你將需要安裝的maven壓縮包放在宿主機的
~/software
路徑,想把它影射成docker內部的/mnt/software
如果java8的基礎鏡像名字是
java-base:1.8
,則運行以下命令啓動一個以此docker實例:$ docker run -it -v ~/software:/mnt/software java-base:1.8 /bin/bash
注意,對於
java-base:1.8
這個鏡像,docker會先搜索本地的images是否存在,如果不存在,默認會到dockerhub上下載。如果你之前是提交到dockerhub的,那還需要增加你的賬戶名(類似於zhangsan/java-base:1.8
)。如果你是提交到自己搭建的私有registry,那麼需要在鏡像名前加上registry的名字(類似於myregistry.net:5000/java-base:1.8
)。- 此時已經attach到docker實例了。將maven壓縮包解壓、拷貝到需要安裝的路徑。
/opt/tool/maven
- 如果有自定義的m2 settings.xml文件,則需要修改實例內部的
~/.m2/
目錄 設置profile文件:
export M2_HOME=/opt/tool/maven export JAVA_HOME=/opt/tool/jdk1.8.0 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:$JAVA_HOME/lib:${JRE_HOME}/lib export PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin
然後退出docker。運行
docker ps -a
找到剛纔退出的docker實例,container id是0d23cb11f494
。然後把這個鏡像提交:$ docker commit 0d23cb11f494 mymaven:3.0
maven鏡像的問題
問題就是,這個看上去標準構建的鏡像,不能運行。
docker運行maven非常簡單:
docker run -it --rm --name maven-test -v `pwd`/project:/usr/src/mymaven mymaven:3.0 mvn package -DskipTests
其中/usr/src/mymaven
是maven在容器中的運行路徑。
在運行時,總是報錯,無法找到$PATH
,也就是找不到maven配置的環境變量。原來是剛纔我們在容器內配置的環境變量,在容器退出後就失效了。每次啓動容器時,docker都重新初始化了環境變量,所以配置的就沒用了。
解決方案
在剛纔創建好的maven鏡像的基礎上,通過Dockerfile的ENV
指令增加對環境變量的配置,再生成一個鏡像。新鏡像中會有處理環境變量的layer,保證環境變量的有效性。
FROM mymaven:3.0
WORKDIR /usr/src/mymaven
ENV M2_HOME=/opt/tool/maven JAVA_HOME=/opt/tool/jdk1.8.0 JRE_HOME=/opt/tool/jdk1.8.0/jre \
CLASSPATH=.:/opt/tool/jdk1.8.0/lib:/opt/tool/jdk1.8.0/lib
ENV PATH=${PATH}:${JAVA_HOME}/bin:${M2_HOME}/bin
COPY ./m2/settings.xml ${HOME}/.m2/settings.xml
然後構建鏡像:
$ docker build -t maven:3.0-jdk-8
再然後,打個tag,push到dockerhub或者你自己的registry。
稍作解釋:
- 多次嘗試後,寫成這樣子。必須將各種HOME的設置放在一個
ENV
layer,然後在此基礎上,在增加一個設置PATH
的ENV
layer才行。 - 將你的
settings.xml
文件放在宿主機,直接COPY
到鏡像中。
用maven鏡像打jar包
打包的命令如下:
sudo docker run -it --rm -v <your-pom-dir>:/usr/src/mymaven maven:3.0-jdk-8 mvn package -DskipTest
鏡像名後的命令就是給容器的運行指令。這樣就可以在<your-pom-dir>/target
中看到打好的包啦!
優化
由於容器是短暫的實體,每次退出後,之前下載的文件並不會保留,所以maven打包時下載的依賴包,每次都要重新下載。可以在啓動時,給容器的/root/.m2
配置一個volume(依賴包默認下載在這個路徑)。這樣下次打包的時候,就會先看本地是否有,沒有再下載:
sudo docker run -it --rm -v <your-pom-dir>:/usr/src/mymaven -v <your-local-m2-volume>:/root/.m2 maven:3.0-jdk-8 mvn package -DskipTest
完。