我们知道maven除了原生支持命令如clean\compile\build\package\install等,这些是maven原生为我们项目提供任务执行功能,比如清除、编译、创建、打包、打包进本地仓库,我们此外我们还可以定制自己的插件来实现功能,比如哪些文件不打包进去,我们这里以dockefile插件为例,了解个各配置及执行流程
dockerfile是spotify提供的一个将项目打成的包打成docker镜像的工具,基于此前它发布的docker-maven-plugin升级而来。通常我们引用该插件如下
<build>
<plugins>
<plugin>
<groupId>com.spotifygroupId>
<artifactId>dockerfile-maven-pluginartifactId>
<version>1.4.9version>
<configuration>
<contextDirectory>${project.basedir}contextDirectory>
<repository>${project.groupId}/${project.artifactId}repository>
<tag>latesttag>
<buildArgs>
<WAR_FILE>${war.explode.directory}WAR_FILE>
buildArgs>
configuration>
plugin>
plugins>
build>
我们的项目是基于tomcat打包的docker文件如下
#默认最新版本
FROM docker.io/tomcat
#设置环境变量
ENV LANG C.UTF-8
ENV TZ=Asia/Shanghai
ENV JAVA_OPTS "-Djava.awt.headless=true"
ENV APP_NAME Demo
ENV CATALINA_HOME /home/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
# 指定日志保存目录
ENV LOG_DIR /home/$APP_NAME/logs
#执行移动命令
RUN mv /usr/local/tomcat /home/tomcat
#执行设置时区操作
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN rm -rf /usr/local/tomcat
RUN rm -rf /home/tomcat/webapps/*
#引用dockerfile插件的参数
ARG WAR_FILE
# 将构建出的主包复制到指定镜像目录中
COPY ${WAR_FILE} /home/tomcat/webapps/ROOT
# 挂载数据卷,指定目录挂载到宿主机上面,为了能够保存(持久化)数据以及共享容器间的数据,为了实现数据共享,例如日志文件共享到宿主机或容器间共享数据.
VOLUME /home/logs /home/$APP_NAME/logs /home/test/logs /home/vipsrv-cache /home/vipsrv-failover
# 启动容器时进入的工作目录
WORKDIR $CATALINA_HOME
#子容器对外暴露端口
EXPOSE 8080
#容器启动时自动执行的脚本,我们一般会将应用启动脚本放在这里,相当于系统自启应用,因为启动后会进入假后台模式,所以要时时输出保证子容器运行
ENTRYPOINT sh /home/admin/tomcat/bin/startup.sh &&tailf /home/admin/tomcat/logs/catalina.out
通常单模块项目我们执行mvn clean package dockerfile:bulid即使创建镜像,docker:tag给镜像打tag,dockerfile:push将镜像推送到仓库,然后服务器端执行pull然后执行就行了
如果我们此时有四个模块,demo-web,demo-service,demo-dao,demo-common,
此时如果将dockerfile放项目及父模块下,执行mvn docker:bulid会发现,子模下没有dockerfile文件,查看依赖关系依赖关系是web->service->dao->common,发现只需要将web模块打包成镜像,此时咋办,如果dockerfile插件依赖和文件进web下,此时需要提前将其他模块install进本地仓库然后web下执行dockerfile:bulid,不能web打包和其他模块打包一起执行命令,也就说我们需要插件执行某个或者些子模块打包镜像操作。此时就要在引出maven-plugin的phase绑定,何为phase,首先看下我们更改的pom依赖配置
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.spotifygroupId>
<artifactId>dockerfile-maven-pluginartifactId>
<version>1.4.9version>
<executions>
<execution>
<id>tag-latestid>
<phase>deployphase>
<goals>
<goal>buildgoal>
<goal>taggoal>
<goal>pushgoal>
goals>
<configuration>
<tag>latesttag>
configuration>
execution>
<execution>
<id>tag-versionid>
<phase>deployphase>
<goals>
<goal>buildgoal>
<goal>taggoal>
<goal>pushgoal>
goals>
<configuration>
<tag>${project.version}tag>
configuration>
execution>
<execution>
<id>defaultid>
<phase>packagephase>
<goals>
<goal>buildgoal>
<goal>taggoal>
goals>
<configuration>
<tag>${project.version}tag>
configuration>
execution>
executions>
<configuration>
<contextDirectory>${project.basedir}contextDirectory>
<repository>${project.groupId}/${project.artifactId}repository>
<tag>latesttag>
<buildArgs>
<WAR_FILE>${war.explode.directory}WAR_FILE>
buildArgs>
configuration>
plugin>
plugins>
pluginManagement>
build>
看了我们配置,发现puglins外面增加了pluginManagement,我们知道两者的区别是,前者是所有子模块都依赖该插件;后者是声明一个插件依赖并且带版本号,类似dependencyManagement作用。我们看到phase绑定一个maven的deploy操作,然后下面是该插件自己的命令,即我们执行deploy时会自动执行bulid、tag、push这些dockerfile插件自带的操作,而且该操作只对依赖了该插件的子模块起作用;
但是但是如果我们package、或者deploy时不想执行打包dockerfile咋办?
此时我们不能绑定,还需要执行dockerfile:bulid命令,但是依旧会发现父模块没有dockerfile,然后我们此时需要跳过插件操作,单独于pluginManagement外加如下
<plugins>
<plugin>
<groupId>com.spotifygroupId>
<artifactId>dockerfile-maven-pluginartifactId>
<configuration>
<skip>trueskip>
configuration>
plugin>
plugins>
此时发现可以跳过了,但是所有子模块跳过了,因此我们改成如下
<plugins>
<plugin>
<inherited>falseinherited>
<groupId>com.spotifygroupId>
<artifactId>dockerfile-maven-pluginartifactId>
<configuration>
<skip>trueskip>
configuration>
plugin>
plugins>
每个模块不继承此插件依赖,但是这样我们需要一一在不需要打包的模块下加此配置,依旧繁琐;我们知道maven如果跳过-Dmaven.test.skip=true 或者-DskipTests,但是于是发现还有dockerfile.skip=true操作,但是依旧时父模块下执行,全局跳过,于是有了如下操作
<dockerfile.skip>truedockerfile.skip>
默认全局跳过,然后需要dockerfile打包镜像的模块加上相反配置,覆盖全局默认跳过即可
<dockerfile.skip>falsedockerfile.skip>
此时我们无论用绑定插件操作还是直接执行插件操作都可以只执行某些需要打包成镜像的模块