美文网首页
pom文件及maven、docker笔记

pom文件及maven、docker笔记

作者: 榷奕 | 来源:发表于2020-01-02 22:54 被阅读0次

    1. pom内容

    pom文件一打开,有这么几个大块的分组:

    (1)dependency

    dependency内部通过groupId,artufactId以及version确定唯一的依赖
    groupId: 组织的唯一标识。
    artifactId: 项目的唯一标识。
    version:项目的版本。

    (2)properties
    应该是自定义的属性值,为了在pom的其他地方引用这些properties
    <properties>
        <mysql.version>5.1.1</mysql.version>
    </properties>
    
    (3)编译插件plugin

    2. spring-boot-maven-plugin

    (1) 如果你的POM是继承spring-boot-starter-parent的话,只需要下面的指定就行。

    <properties>
        <!-- The main class to start by executing java -jar -->
        <start-class>com.mycorp.starter.HelloWorldApplication</start-class>
    </properties>
    

    (2)如果你的POM不是继承spring-boot-starter-parent的话,需要下面的指定。

        <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
          <version>1.3.5.RELEASE</version>
          <configuration>
            <mainClass>${start-class}</mainClass>
            <layout>ZIP</layout>
          </configuration>
          <executions>
            <execution>
              <goals>
                <goal>repackage</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
    

    上面这两种情况的原理,是由于你引入了<parent>,然后springboot的parent在build的子标签里面有pluginManagement,已经把springboot-maven-plugin这个插件的很多都写出来了,唯一就是引用了一个${start-class},所以你补上就行。
    如果没继承这个parent,那么写出来的跟抄这个parent下面是一样的。
    (这里又涉及到另一个只是,只要是pom里面的Maganement,无论是dependencyManagement还是pluginManagement,都是在父工程里面用的,在父工程里面用了之后,子工程直接继承,所以你多半不会自己去主动定义。)

                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>repackage</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <mainClass>${start-class}</mainClass>
                        </configuration>
                    </plugin>
    
    • configuration:该插件所需要的特殊配置,在父子项目之间可以覆盖或合并
    • executions:plugin 可以有多个目标,每一个目标都可以有一个分开的配置,甚至可以绑定一个 plugin 的目标到一个不同的阶段。executions 配置一个 plugin 的目标的 execution。一个 execution 有如下设置:
      • id,唯一标识
      • goals,要执行的插件的 goal(可以有多个),如 <goal>repackage</goal>
      • phase,目标执行的阶段,具体值看Maven的生命周期列表
      • inherited,该 execution 是否可被子项目继承
      • configuration,该 execution 的其他配置参数
        (execution里面的这几个子项,应该只有上三个有用。以及这些都是事先被定义好的流程,你写的这些都是在给别人的框架传配置。)

    execution是一个执行任务,configuration是这个任务能用到的参数,有一些configuration是plugin用的,有一些是execution用的,反正都是框架定义好的参数,你只要传递就行了。
    execution里面有用的只有一个goal,goal应该只会需要repackage模式,经过了这个repackage之后,打出来的包才有两个,一个是.original,一个是.jar,maven第一次打出来的包再次打包的时候变成了.original,然后第二次打包结果变成.jar。从体积上来计算,.original是几百k,源代码也是几百k,而.jar是几十兆,应该是一个胖包一个瘦包,再次打包的过程把所有的依赖都打进去了。

    3. docker-maven-plugin

    思路:首先知道根据dockerfile是怎么打包的,
    这里开始解析dockerfile里面的每一句,
    然后把dockerfile变成pom里面的<>。

    (1) dockerfile内容
    #父镜像
    FROM java:8
    #拷贝jar包
    ADD scm.jar app.jar
    #暴露接口
    EXPOSE 8080
    #启动容器的时候运行jar包
    ENTRYPOINT [ "java", "-jar", "/app.jar" ]
    

    如果真写起来dockerfile的话,上面应该就够用了。
    dockerfile里面的四句话,父镜像,添加jar,运行jar,-p暴露端口。
    (要调研的应该也就是Add和Entrypoint这两个有什么区别,或者不调研了)
    Copy和Add用法好像一样的,都是Copy/Add + 要复制的jar + 别名

    (2)使用dockefile结合插件
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!--使用docker-maven-plugin插件-->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.0.0</version>
    
                <!--将插件绑定在某个phase执行,下面的这个execution发挥的作用就是把这个docker打包镜像的过程绑定到了maven-plugin上面去-->
                <executions>
                    <execution>
                        <id>build-image</id>
                        <!--用户只需执行mvn package ,就会自动执行mvn docker:build-->
                        <phase>package</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
    
                <configuration>
                    <!--指定生成的镜像名-->
                    <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
                    <!--指定标签-->
                    <imageTags>
                        <imageTag>latest</imageTag>
                    </imageTags>
                    <!-- 指定 Dockerfile 路径-->
                    <dockerDirectory>${project.basedir}</dockerDirectory>
                    <!--指定远程 docker api地址-->
                    <dockerHost>http://10.112.158.59:2375</dockerHost>
    
                    <!-- 这里是复制 jar 包到 docker 容器指定目录配置,相当于dockerfile里面的那句Add -->
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <!--需要复制的jar 包所在的路径  此处配置的 即对应 target 目录,这个表达式你背下来就行了不用变-->
                            <directory>${project.build.directory}</directory>
                            <!-- 需要复制的 jar包 ,这里对应的是 Dockerfile中添加的文件名,也是背下来就行了 -->
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    (3) 完全使用pom文件

    这个是结合上面的那一份代码,改动了其中的dockerfile的那一句,变成了另外三句(其中的copy语句是下面的resource)。
    以及下面这份文档应该是可以直接复制的,除了中间有服务器地址和端口号两个之外感觉别的都不用变。

    <build>
            <finalName>${project.artifactId}</finalName>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
    
    
                <!-- 跳过单元测试 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <skipTests>true</skipTests>
                    </configuration>
                </plugin>
    
                <!--使用docker-maven-plugin插件-->
                <plugin>
                    <groupId>com.spotify</groupId>
                    <artifactId>docker-maven-plugin</artifactId>
                    <version>1.0.0</version>
                    <!--将插件绑定在某个phase执行-->
                    <executions>
                        <execution>
                            <id>build-image</id>
                            <!--用户只需执行mvn package ,就会自动执行mvn docker:build-->
                            <phase>package</phase>
                            <goals>
                                <goal>build</goal>
                            </goals>
                        </execution>
                    </executions>
    
                    <configuration>
    <!--                    这里是生成dockerfile的,也就是不需要自己写dockerfile了,直接在这个pom里面定义!!!!流弊!!!
                               dockerfile里面的每一行在这里面都有一个标签名<>对应着-->
                        <!--指定生成的镜像名,这里注意docker生成文件的前缀,在上面要有一个properties来定义这个前缀-->
                        <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
                        <!--指定标签-->
                        <imageTags>
                            <imageTag>latest</imageTag>
                        </imageTags>
                        <!--指定远程 docker api地址(!!!这里要变化)-->
                        <dockerHost>http://10.112.158.59:2375</dockerHost>
    
                        <!-- 指定 Dockerfile 路径-->
    <!--                    <dockerDirectory>${project.basedir}</dockerDirectory>-->
    
                        <!-- 从这里开始是重点了-->
                        <baseImage>java:8</baseImage>
                        <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
                        <exposes>
                            <!--(!!!)这个暴露接口也要变化 -->
                            <expose>7050</expose>
                        </exposes>
    
                        <!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
                        <resources>
                            <resource>
                                <targetPath>/</targetPath>
                                <!--jar 包所在的路径  此处配置的 即对应 target 目录-->
                                <directory>${project.build.directory}</directory>
                                <!-- 需要包含的 jar包 ,这里对应的是 Dockerfile中添加的文件名 -->
                                <include>${project.build.finalName}.jar</include>
                            </resource>
                        </resources>
                    </configuration>
    
                </plugin>
            </plugins>
        </build>
    
    (4) 生成镜像之后是要用下面的视图来启动容器的

    至于这个视图启动容器看着就简单,就不写了。

    4. maven

    (1) maven项目结构

    构建打包技术,发展历史是make -> ant -> maven -> gradle

    maven工程中各目录结构含义

    也就是说现在的工程就是一个maven工程,所以现在的src、pom、resource什么的全都是由这个maven工程来决定的,这是maven的约定,让maven知道什么的东西放在哪里,然后可以自动化构建。、

    (2)maven依赖

    首先是依赖的排除,一定是一个很大的依赖,里面一堆二级子依赖,然后这里面的一堆想排除哪个哪个,在这个大依赖的标签下面写排除。

    <dependency>
         <exclusion>
    

    然后是依赖冲突,如果对于一个依赖的好几个版本都声明了,两个原则。首先是路径最短的优先,你直接引用是要比在别的大包里面带进来要优先的;如果路径一样,先声明的优先,如果都是大包带进来的,那么排在上面的优先。

    最后是统一管理依赖的版本。原理大概就是在pom里面的<properties>里面声明各种自定义属性,然后在下面引用dependency的时候,在version里面用${}来引用上面定义的属性。应该是应用于一个体系的框架内的所有引用,比如spring框架的很多东西,把这些所有与spring相关的引用版本保持一致。

    (3) maven生命周期
    • clean应该是删除target吧
    • compile是把.java变成.class文件
    • test是执行test文件夹里面的测试程序
    • package是在target文件夹里面生成很多包括jar包在内的很多东西
    • install是把jar包拷贝到本地的maven仓库,然后本机上的其他工程就能引用这个工程的依赖。
    • deploy是把jar包拷贝到servlet里面运行,这个目前没啥用了,达到的效果是在本机上把程序跑起来,有一种愚蠢的启动办法,是把项目打包成jar包,然后把jar包拷贝到Tomcat里面去运行,deploy完成了这个功能,当然现在都能用Idea直接run就没必要了。
    • site也是只能在服务器上执行的,用Shell命令mvn site xxxx什么的,所以没啥卵用。

    所以总结,最终在idea上的mvn插件里面有用的仍然只有一个clean和package。
    以及maven的常用命令,mvn开头的那几个Linux命令,完完全全就对应了上面的这几个指令,clean、test、package什么的。

    (4) maven的坐标

    跟上面的maven依赖联系起来。

    • groupId:组织标识,一般为:公司网址的反写+项目名
    • artifactId:项目名称,一般为:项目名-模块名
    • version:版本号

    所有的maven项目都要有上面的三个坐标,三个加起来就在仓库里面唯一确定了这个依赖。dependency引用的时候也是用这三个加起来就能指定到底引用哪一个项目,所以dependency下面有用的也是这三个。

    (5)继承 <parent>

    这个是为了在一个父工程里面统一管理依赖版本的。
    用处就是在父工程里面定义一个<dependencyManagement>,在这里面定义各种<dependency>,写上版本号。
    再之后在子工程里面继承这个parent,子工程里面再引用各种dependency的时候就可以不写版号了。
    (这个parent不能给子工程引入依赖,只是对依赖版本version的统一管理)

    (6)聚合 <module>

    module这个,如果聚合起来了的话,从parent入口那里可以直接把所有的项目一键打包并且复制到本机的Tomcat,所有工程的一键部署吧(学了之后感觉没卵用)

    (7)依赖作用范围<scope>

    这个就是表示这个依赖会在哪里起作用,会不会进入最终的jar包吧,如果不配置默认是打进jar包的。

    • compile,缺省值,适用于所有阶段,会打包进项目。
    • provided,类似compile,期望JDK、容器或使用者会提供这个依赖。
    • runtime,只在运行时使用,如JDBC驱动,适用运行和测试阶段。
    • test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。
    • system,类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它。

    相关文章

      网友评论

          本文标题:pom文件及maven、docker笔记

          本文链接:https://www.haomeiwen.com/subject/cqtaoctx.html