使用maven-docker工具快速构建可交付的java-web镜像
  JmMM2CFhUghs 2023年11月02日 30 0


容器的出现让 Java开发人员比以往任何时候都更接近“编写一次,到处运行”的工作流程,然而在实际的工作中并非这样的~!要实现这样的诉求,首先你必须编写 Dockerfile,以 root身份运行 Docker守护进程,等待构建完成,最后将镜像推送到远程注册中心。说实话,Dockerfile有多复杂也有文章讲过,但并非所有的 Java开发人员都是容器专家。下面带着这些疑问,给大家介绍下java开源世界常用docker-maven-plugin、dockerfile-maven-plugin、jib-maven-plugin,工具的好坏,重要的看自己的喜好。

One-JAR的魅力在于:

  • 可以用 java -jar 机制执行。
  • 能够包含应用程序需要的 所有文件 —— 也就是说, 包括原始形式(未展开)的类和资源。
  • 拥有简单的内部结构,仅仅用 jar工具就可以被装配起来。
  • 对原来的应用程序不可见 —— 也就是说,无需修改原来的应用程序,就可以把它打包在 One-JAR 档案文件内部。

目录

1. docker-maven-plugin

历程

声明构建信息

使用Dockerfile

构建

使用私有镜像中心

认证

2. dockerfile-maven-plugin

约束

示例

它可以带来什么?

授权

配置

3. jib-maven-plugin

快速开始


1. docker-maven-plugin

2016-4月份由Spotify开源的,当前版本v1.1.1,一个,用于构建和上传docker镜像的Maven插件,官方介绍

历程

这个插件是Spotify使用的最初的Maven插件,用于从Java服务中构建DOCKERr镜像。它最初创建于2014,当我们第一次开始试验Docker。这个插件能够基于pom.xml文件中的配置为您生成一个Dockerfile,用于FROM映像、添加ADD/COPY等内容。

Spotify随着时间的推移,我们意识到,从Java项目中构建DOCKERr镜像最简单的方法是让开发人员编写DOCKFILE文件。这个插件在生成Dockerfile、将项目目录复制到“.ing”目录以作为Docker构建上下文等等方面的行为最终导致了与用户之间的许多不必要的混淆,这些混淆源于引入额外的抽象和对配置的需要。最重要的是Docker提供的东西。

这导致创建了用于构建docker映像的第二个Maven插件,dockerfile-maven,我们认为它为使用来自Maven的Docker提供了一个更简单的思维模型,原因都在dockerfile-maven的README中列出。

默认情况下,该插件通过访问localhost:2375来连接本地docker,可以通过设置DOCKER_HOST 环境变量来连接docker.

DOCKER_HOST=tcp://<host>:2375

声明构建信息

此示例创建一个名为example的新镜像,将项目的jar文件复制到镜像中,并设置运行jar的入口点。更改版本到最新的标签版本。

<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>docker-maven-plugin</artifactId>
  <version>VERSION GOES HERE</version>
  <configuration>
    <imageName>example</imageName>
    <baseImage>java</baseImage>
    <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
    <!-- copy the service's jar file from target into the root directory of the image -->
    <resources>
       <resource>
         <targetPath>/</targetPath>
         <directory>${project.build.directory}</directory>
         <include>${project.build.finalName}.jar</include>
       </resource>
    </resources>
  </configuration>
</plugin>

参数解释:

  • imageName:镜像的名称,可以通过${project.groupId}/${project.artifactId}:${project.version} 动态制定镜像名称。当然也可以在前面加上镜像地址,比如127.0.0.1:5000,以声明将构建好的镜像存储在本地
  • baseImage: 基础镜像,这里是相当于Dockerfile的FROM java
  • resources 下的配置:构建时会生成docker文件夹,这里指生成文件夹的内容来源,包含了mvn clean package 之后的target的文件和生成的jar包。

使用Dockerfile

为了使用Dockerfile,必须在pom的文件中通过dockerDirectory来指明Dockerfile文件的所在目录。如果配置了dockerDirectory,baseImage,maintainer,cmd和entryPoint配置将忽略。下面的配置会将dockerDirectory的内容拷贝值${project.build.directory}/docker,使用resouces元素可以拷贝其他的文件,比如生成jar包文件。

<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>docker-maven-plugin</artifactId>
  <version>VERSION GOES HERE</version>
  <configuration>
    <imageName>example</imageName>
    <dockerDirectory>docker</dockerDirectory>
    <resources>
       <resource>
         <targetPath>/</targetPath>
         <directory>${project.build.directory}</directory>
         <include>${project.build.finalName}.jar</include>
       </resource>
    </resources>
  </configuration>
</plugin>

构建

  • 生成一个镜像,mvn clean package docker:build
  • 将生成的镜像推送到镜像注册中心,mvn clean package docker:build -DpushImage
  • 如果推送制定tags 的镜像,mvn clean package docker:build -DpushImageTag

绑定docker命令到maven phases

<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>docker-maven-plugin</artifactId>
  <version>VERSION GOES HERE</version>
  <executions>
    <execution>
      <id>build-image</id>
      <phase>package</phase>
      <goals>
        <goal>build</goal>
      </goals>
    </execution>
    <execution>
      <id>tag-image</id>
      <phase>package</phase>
      <goals>
        <goal>tag</goal>
      </goals>
      <configuration>
        <image>my-image:${project.version}</image>
        <newName>registry.example.com/my-image:${project.version}</newName>
      </configuration>
    </execution>
    <execution>
      <id>push-image</id>
      <phase>deploy</phase>
      <goals>
        <goal>push</goal>
      </goals>
      <configuration>
        <imageName>registry.example.com/my-image:${project.version}</imageName>
      </configuration>
    </execution>        
  </executions>
</plugin>

可以通过一下命令跳过docker构建的阶段

  • DskipDockerBuild 跳过镜像构建
  • DskipDockerTag 跳过镜像tag设置
  • DskipDockerPush 跳过镜像推送
  • DskipDocker 跳过所有的镜像构建目标

删除一个名称为foobar的镜像
mvn docker:removeImage -DimageName=foobar
获取完成的配置选项列表
mvn com.spotify:docker-maven-plugin:<version>:help -Ddetail=true

使用私有镜像中心

为了将镜像推送到私有的镜像注册中心,docker需要在镜像tag之前用注册中心的地址作为前缀。比如需要推送my-image到registry.example.com,那么这个镜像需要命名为registry.example.com/my-image
最简单的方法就是在<imageName>中配置:

<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>docker-maven-plugin</artifactId>
  <configuration>
    <imageName>registry.example.com/my-image</imageName>
...

这样,当你通过命令docker:build -DpushImage或者docker:push推送镜像时,docker引擎会将镜像推送到registry.example.com.

当然你可以在docker:build命令中通过 docker:tag -DpushImage对创建的镜像加上私有镜像注册中心的地址,如不配置,则会推送到默认的镜像中心,即Docker hub;你也可如下这样配置:

<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>docker-maven-plugin</artifactId>
  <configuration>
    <imageName>my-image</imageName>
    ...
  </configuration>
  <executions>
    <execution>
      <id>build-image</id>
      <phase>package</phase>
      <goals>
        <goal>build</goal>
      </goals>
    </execution>
    <execution>
      <id>tag-image</id>
      <phase>package</phase>
      <goals>
        <goal>tag</goal>
      </goals>
      <configuration>
        <image>my-image</image>
        <newName>registry.example.com/my-image</newName>
      </configuration>
    </execution>
  </executions>
</plugin>

认证

支持三种认证方式:
1. 读取本地配置文件,自动认证
从1.0.0版本之后,docker-maven-plugin插件会自动读取到docker-cli的认证配置,默认在~/.dockercfg 和~/.docker/config.json,而无需额外的配置

2. GCR认证
如果本机配置DOCKER_GOOGLE_CREDENTIALS的环境变量,则会使用GCR认证。

3. Server认证

<!--也可以在maven的settings.xml配置认证信息: -->
<servers>
  <server>
    <id>docker-hub</id>
    <username>foo</username>
    <password>secret-password</password>
    <configuration>
      <email>foo@foo.bar</email>
    </configuration>
  </server>
</servers>
<!--在pom.xml则通过如下配置关联上述server id -->
<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>docker-maven-plugin</artifactId>
  <version>VERSION GOES HERE</version>
  <configuration>
    [...]
    <serverId>docker-hub</serverId>
    <registryUrl>https://index.docker.io/v1/</registryUrl>
  </configuration>
</plugin>

以上三种配置方式中,通过读取客户端默认配置的优先级更高。

在server配置中加密密码
为了不在配置文件中不暴露明文密码,可以使用maven加密功能对密码进行加密,通过{ }方式都认为是被加密的密码

<servers>
  <server>
    <id>docker-hub</id>
    <username>foo</username>
    <password>{gc4QPLrlgPwHZjAhPw8JPuGzaPitzuyjeBojwCz88j4=}</password>
  </server>
</servers>

2. dockerfile-maven-plugin

上面讲过,Spotify的第二个版本,官方介绍

  • 不要做任何花哨的事。dockerfile是如何构建DOCKER项目;这就是插件使用的内容。它们是强制性的。
  • 使DOCKER构建过程与Maven构建过程集成。如果绑定默认阶段,则在键入mvn package时,会得到docker映像。当您键入mvn deploy时,您的镜像会被推送。
  • 让目标记住你在做什么。您可以键入mvn dockerfile:buildmvn dockerfile:tag和稍后的mvn dockerfile:push无问题。这也消除了对诸如mvn dockerfile:build -DalsoPush之类的东西的需求;相反,您可以只说mvn dockerfile:build dockerfile:push
  • 与Maven构建集成。您可以依赖于另一个项目中的一个项目的DOCKERr镜像,而Maven将按照正确的顺序构建项目。当您想要运行涉及多个服务的集成测试时,这是有用的。

约束

这个插件需要Java 7或更高版本和Apache Maven 3或更高版本。要运行集成测试或在实践中使用插件,需要一个docker环境。

示例

<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>dockerfile-maven-plugin</artifactId>
  <version>${dockerfile-maven-version}</version>
  <executions>
    <execution>
      <id>default</id>
      <goals>
        <goal>build</goal>
        <goal>push</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <repository>spotify/foobar</repository>
    <tag>${project.version}</tag>
    <buildArgs>
      <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
    </buildArgs>
  </configuration>
</plugin>

对应的docker镜像可以是:

FROM openjdk:8-jre
MAINTAINER David Flemström <dflemstr@spotify.com>

ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/myservice/myservice.jar"]

# Add Maven dependencies (not shaded into the artifact; Docker-cached)
ADD target/lib           /usr/share/myservice/lib
# Add the service itself
ARG JAR_FILE
ADD target/${JAR_FILE} /usr/share/myservice/myservice.jar

它可以带来什么?

1.更快的建造时间,这个插件允许您更一致地利用Docker缓存,通过让您在映像中缓存Maven依赖项,极大地加快了构建的速度。它还鼓励避免maven-shade-plugin,这也大大加快了构建。

2.一致的构建生命周期

mvn package
mvn dockerfile:build
mvn verify
mvn dockerfile:push
mvn deploy

3.依赖docker镜像上的其他服务,您可以依赖于另一个项目的Docker信息,因为这个插件在构建Docker映像时附加项目元数据。只需将此信息添加到任何项目

4.使用依赖Dockerfiles的其他docker工具

<!--你的项目是这样的: -->
a/
     Dockerfile
     pom.xml
b/
     Dockerfile
     pom.xml
<!--现在您可以使用这些项目与Fig或docker-compose或一些其他系统与Dockerfiles合作。例如,docker-compose.yml: -->
service-a:
  build: a/
  ports:
  - '80'

service-b:
  build: b/
  links:
  - service-a

授权

更多

配置

更多

3. jib-maven-plugin

google 于2018-7开源的,通过 Jib,我们不需要编写 Dockerfile 或安装 Docker,通过集成到 Maven 或 Gradle 插件,就可以立即将 Java 应用程序容器化。官方介绍

优点

  • 无需编写Dockerfile,甚至无需安装docker
  • 无需再执行docker build、push命令了
  • 增量构建镜像,无需每次编译项目先打包jar

缺点

  • 默认拉取的基础镜像是gcr仓库需要翻墙(可以国内的阿里云镜像服务),并且jdk默认是openjdk
  • 在拉取自定义的基础镜像和push构建的镜像这块,设计的不够友好,依赖需要第三方的加密组件(折腾了好一会);
  • 侵入性太强,需要每个项目都添加上maven插件。如果是现有方案,只需要添加一个Dockerfile就可以了,而且定制化高
  • 只支持java平台

快速开始

<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.alex.sample.lib</groupId>
    <artifactId>helloworld-samples</artifactId>
    <version>0.1</version>
    <packaging>jar</packaging>
    <name>helloworld-samples</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jib-maven-plugin.version>1.0.2</jib-maven-plugin.version>
        <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
    </properties>
    <dependencies>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <!-- Jib -->
            <plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>jib-maven-plugin</artifactId>
                <version>${jib-maven-plugin.version}</version>
                <configuration>
                    <from>
                        <image>registry.cn-hangzhou.aliyuncs.com/alex/oracle_java8</image>
                    </from>
                    <to>
                        <image>registry.cn-hangzhou.aliyuncs.com/alex/jib-helloworld:v1</image>
                    </to>
                    <container>
                        <jvmFlags>
                            <jvmFlag>-Xms512m</jvmFlag>
                            <jvmFlag>-Xdebug</jvmFlag>
                        </jvmFlags>
                        <mainClass>com.alex.HelloWorld</mainClass>
                    </container>
                </configuration>
                <executions>
                    <execution><!--绑定生命周期,可以运行mvn package-->
                        <phase>package</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
<!-- 如果"登录失败,未授权",需要通过 docker login 登录鉴权一下。此外,更好的做法是,你可以考虑在Maven 中放置凭据 -->
<settings>
  <servers>
    ...
        <server>
        <id>registry.cn-hangzhou.aliyuncs.com</id>
        <username>你的阿里云账号</username>
        <password>你的阿里云密码</password>
        </server>
  </servers>
</settings>

构建镜像
mvn compile jib:build
把镜像直接构建到本地docker中
mvn compile jib:dockerBuild
把镜像直接构建到本地磁盘(target/jib-image.tar)
mvn compile jib:buildTar
这样,可以从本地启动
docker load --input target/jib-image.tar
导出一个Docker context
mvn compile jib:exportDockerContext -DjibTargetDir=my/docker/context/
可以使用docker build image
docker build -t myimage my/docker/context/

其他参数说明更多

最后,工具没有好坏之说,但个人推荐使用jib-maven-plugin,功能特性上稍稍丰富一些,另外就是google的魅力。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  PVcilKyJJTzb   2023年11月02日   54   0   0 Bashdockergit
  PVcilKyJJTzb   2023年11月02日   49   0   0 nginxdockerhtml
  Q61SiiCoGao8   2023年11月02日   29   0   0 linuxdockerubuntu配置文件
  Q61SiiCoGao8   2023年11月02日   48   0   0 nginxdockerDockerfile
  CZHsu4xuhYFz   2023年11月02日   25   0   0 nginxPoddocker
  jmWSp8RIQOBK   2023年11月02日   33   0   0 MySQLdocker
  PVcilKyJJTzb   2023年11月02日   64   0   0 Bashdocker堆栈
JmMM2CFhUghs