写点什么

maven 构建 docker 镜像三部曲之二:编码和构建镜像

作者:程序员欣宸
  • 2022 年 5 月 02 日
  • 本文字数:6295 字

    阅读完需:约 21 分钟

maven构建docker镜像三部曲之二:编码和构建镜像

欢迎访问我的 GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos


本篇概览

web 工程

  • 我们采用 spring boot 的 web 工程作为实战的应用,这样的好处是简单快速的创建和部署项目,这只是个最简单的、基于 maven 构建的 spring boot web 工程,源码我已经上传到 github 上,地址是:git@github.com:zq2599/blog_demos.git,浏览器访问地址是:https://github.com/zq2599/blog_demos, 这里面有多个工程,本次实战用到的是 mavendockerplugindemo,如下图红框所示:

java 代码

  • mavendockerplugindemo 工程的代码非常简单,只有一个 controller,如下图:

pom.xml

  • 整个工程的 pom.xml 也很简单,依赖 spring-boot-starter-web,构建的时候使用 spring-boot-maven-plugin 插件,如下:

<?xml version="1.0" encoding="UTF-8"?><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.bolingcavalry</groupId> <artifactId>mavendockerplugindemo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>mavendockerplugindemo</name> <description>maven docker plugin demo</description>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath/> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
复制代码


  • 正常情况下,工程运行起来后在浏览器访问 http://x.x.x.x:8080,就会显示如下信息(x.x.x.x 代表执行工程的机器 ip):

将工程复制到 linux 虚拟机上


  1. 在 windows 电脑上,我将工程压缩成 mavendockerplugindemo.zip 文件,存放在 D:\blog 目录下;

  2. 在 linux 虚拟机新建目录**/usr/local/work**;

  3. 在 linux 虚拟机执行命令 apt-get install -y unzip,安装解压工具;

  4. 复制文件,推荐使用 SecureCRT 的 SFTP 工具,先用 SecureCRT 登录虚拟机,再建立 SFTP 连接,如下图红框所示:

  5. 在 SFTP 窗口执行以下命令:


#进入本机的d:/blog/目录lcd d:/blog/#进入linux的/usr/local/work/目录cd /usr/local/work/#将本机d:/blog/目录下的mavendockerplugindemo.zip文件上传到linux的/usr/local/work/目录下put mavendockerplugindemo.zip
复制代码


  • 这样就能将文件从 windows 电脑传到 linux 虚拟机上,如果想把 linux 虚拟机上的 xxx 文件下载到 windows 电脑,执行 get xxx 命令即可;


  1. 关闭 SFTP 窗口,在 ssh 窗口进入/usr/local/work/,执行命令 unzip mavendockerplugindemo.zip 将工程解压缩;

  2. 请注意:接下来的操作都在 linux 虚拟机上进行;

镜像构建方式

  • docker-maven-plugin 插件构建 docker 镜像有两种方式:

  1. 指定参数,由 docker-maven-plugin 插件根据这些参数来制作镜像;

  2. 指定 Dockerfile,这和我们用 docker build 命令来构建镜像的过程一样,不过 docker-maven-plugin 帮我们把工程构建和镜像构建两件事串起来了;

  • 接下来我们将上述两种方式都实践一下;

第一种构建方式:通过参数构建


  • 在 mavendockerplugindemo 工程目录下新建文件 pom_1_by_param.xml,内容和 pom.xml 一样,然后我们再去<plugins>节点添加以下内容,放在原有的<plugin>节点后面,如下所示:


<plugins>      <!--这是原有的spring boot插件-->      <plugin>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-maven-plugin</artifactId>      </plugin>      <!--新增的docker maven插件-->      <plugin>        <groupId>com.spotify</groupId>        <artifactId>docker-maven-plugin</artifactId>        <version>0.4.12</version>        <!--docker镜像相关的配置信息-->        <configuration>          <!--镜像名,这里用工程名-->          <imageName>${project.artifactId}</imageName>          <!--TAG,这里用工程版本号-->          <imageTags>            <imageTag>${project.version}</imageTag>          </imageTags>          <!--镜像的FROM,使用java官方镜像-->          <baseImage>java:8u111-jdk</baseImage>          <!--该镜像的容器启动后,直接运行spring boot工程-->          <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>          <!--构建镜像的配置信息-->          <resources>            <resource>              <targetPath>/</targetPath>              <directory>${project.build.directory}</directory>              <include>${project.build.finalName}.jar</include>            </resource>          </resources>        </configuration>      </plugin>    </plugins>
复制代码


  • 上面的每个参数都已加了注释,就不多说了,在此文件所在目录执行以下命令,指定 pom_1_by_param.xml 作为 pom 文件执行 maven 构建:

mvn -f pom_1_by_param.xml clean package -DskipTests docker:build
复制代码


  • 执行成功后输出以下信息:

[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ mavendockerplugindemo ---[INFO] Building jar: /usr/local/work/mavendockerplugindemo/target/mavendockerplugindemo-0.0.1-SNAPSHOT.jar[INFO] [INFO] --- spring-boot-maven-plugin:1.5.9.RELEASE:repackage (default) @ mavendockerplugindemo ---[INFO] [INFO] --- docker-maven-plugin:0.4.12:build (default-cli) @ mavendockerplugindemo ---[INFO] Copying /usr/local/work/mavendockerplugindemo/target/mavendockerplugindemo-0.0.1-SNAPSHOT.jar -> /usr/local/work/mavendockerplugindemo/target/docker/mavendockerplugindemo-0.0.1-SNAPSHOT.jar[INFO] Building image mavendockerplugindemoStep 1/3 : FROM java:8u111-jdk ---> d23bdf5b1b1bStep 2/3 : ADD /mavendockerplugindemo-0.0.1-SNAPSHOT.jar // ---> 74f201b46c92Removing intermediate container cbc9e456d139Step 3/3 : ENTRYPOINT java -jar /mavendockerplugindemo-0.0.1-SNAPSHOT.jar ---> Running in 256a09be033d ---> ad342e51021eRemoving intermediate container 256a09be033dSuccessfully built ad342e51021e[INFO] Built mavendockerplugindemo[INFO] Tagging mavendockerplugindemo with 0.0.1-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 11.617 s[INFO] Finished at: 2017-12-23T00:00:06-08:00[INFO] Final Memory: 35M/84M[INFO] ------------------------------------------------------------------------
复制代码


  • 执行 docker images 命令可以看到如下信息,新的镜像已经创建好了:

REPOSITORY              TAG                 IMAGE ID            CREATED             SIZEmavendockerplugindemo   0.0.1-SNAPSHOT      ad342e51021e        10 minutes ago      658 MBmavendockerplugindemo   latest              ad342e51021e        10 minutes ago      658 MBjava                    8u111-jdk           d23bdf5b1b1b        11 months ago       643 MB
复制代码


  • 为什么会有两个名为 mavendockerplugindemo 的镜像呢?看一下 maven 的构建日志,有下面这么一句:

[INFO] Tagging mavendockerplugindemo with 0.0.1-SNAPSHOT
复制代码


  • 原来是以构建好的 latest 镜像的基础,按照我们的配置上做了一次 TAG 操作,本身镜像是同一个(IMAGE ID 相同);

验证第一种方式构建的镜像

  • 执行以下命令,使用刚刚构建的镜像创建一个容器:

docker run --name demo001 -p 8080:8080 mavendockerplugindemo:0.0.1-SNAPSHOT
复制代码
  • 启动信息如下所示:

  • 我这里 linux 虚拟机的 IP 是 192.168.119.155,所以在 windows 上打开浏览器,输入地址:192.168.119.155:8080,看到如下效果,web 项目正常启动:


第二种构建方式:指定 Dockerfile

  • 这种方式要我们自己写 Dockerfile,好处是可以按照自己的需要在 Dockerfile 中添加更多内容,而不像第一种方式那样只能按照插件的参数规则来配置;

  • 先把之前的容器停掉,现在虚拟机的控制台应该还是刚刚我们启动的容器的输出,键入“Ctrl + c”退出此容器,这样才会解除 8080 端口的占用;

  • 在 mavendockerplugindemo 工程目录下新建文件 pom_2_by_dockerfile.xml,内容和 pom.xml 一样,然后我们再去<plugins>节点添加以下内容,放在原有的<plugin>节点后面,如下所示:

<!--新增的docker maven插件-->      <plugin>        <groupId>com.spotify</groupId>        <artifactId>docker-maven-plugin</artifactId>        <version>0.4.12</version>        <!--docker镜像相关的配置信息-->        <configuration>          <!--镜像名,这里用工程名-->          <imageName>${project.artifactId}</imageName>          <!--Dockerfile文件所在目录-->          <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>          <!--TAG,这里用工程版本号-->          <imageTags>            <imageTag>${project.version}</imageTag>          </imageTags>          <!--构建镜像的配置信息-->          <resources>            <resource>              <targetPath>/</targetPath>              <directory>${project.build.directory}</directory>              <include>${project.build.finalName}.jar</include>            </resource>          </resources>        </configuration>      </plugin>
复制代码


  • 和之前的 pom_1_by_param.xml 相比有如下变动:

  1. 新增<dockerDirectory>节点用来表示自定义 Dockerfile 文件的位置;

  2. <baseImage>和<entryPoint>节点用不上了,在此删掉;

  • 为了和第一种构建结果区分开,把 pom_2_by_dockerfile.xml 中定义的工程版本号从 0.0.1-SNAPSHOT 改为 0.0.2-SNAPSHOT,如下所示:

  <groupId>com.bolingcavalry</groupId>  <artifactId>mavendockerplugindemo</artifactId>  <version>0.0.2-SNAPSHOT</version>  <packaging>jar</packaging>
复制代码
  • 在工程的 src/main/docker/目录下新建 Dockerfile 文件,如下图:

  • Dockerfile 的内容如下,就是将工程构建完毕后的 jar 包复制到 home 目录,然后构建镜像:

ENV ARTIFACTID mavendockerplugindemoENV ARTIFACTVERSION 0.0.2-SNAPSHOTENV HOME_PATH /home
ADD /$ARTIFACTID-$ARTIFACTVERSION.jar $HOME_PATH/mavendockerplugindemo.jar
WORKDIR $HOME_PATH
ENTRYPOINT ["java","-jar","mavendockerplugindemo.jar"]
复制代码


  • 可以开始构建了,在 pom_2_by_dockerfile.xml 所在目录执行以下命令:

mvn -f pom_2_by_dockerfile.xml clean package -DskipTests docker:build
复制代码


  • 会看到如下输出信息:

[INFO] --- docker-maven-plugin:0.4.12:build (default-cli) @ mavendockerplugindemo ---[INFO] Copying /usr/local/work/mavendockerplugindemo/target/mavendockerplugindemo-0.0.2-SNAPSHOT.jar -> /usr/local/work/mavendockerplugindemo/target/docker/mavendockerplugindemo-0.0.2-SNAPSHOT.jar[INFO] Copying /usr/local/work/mavendockerplugindemo/src/main/docker/Dockerfile -> /usr/local/work/mavendockerplugindemo/target/docker/Dockerfile[INFO] Building image mavendockerplugindemoStep 1/7 : FROM java:8u111-jdk ---> d23bdf5b1b1bStep 2/7 : ENV ARTIFACTID mavendockerplugindemo ---> Using cache ---> bf895524c43eStep 3/7 : ENV ARTIFACTVERSION 0.0.2-SNAPSHOT ---> Using cache ---> 1837d1412faeStep 4/7 : ENV HOME_PATH /home ---> Using cache ---> 6220811f7777Step 5/7 : ADD /$ARTIFACTID-$ARTIFACTVERSION.jar $HOME_PATH/mavendockerplugindemo.jar ---> 9f174f1e3c65Removing intermediate container 9a8bc49917f4Step 6/7 : WORKDIR $HOME_PATH ---> a34f05e5a272Removing intermediate container 4bd7c136607dStep 7/7 : ENTRYPOINT java -jar mavendockerplugindemo.jar ---> Running in 3122df8b7121 ---> 5914eaeb88abRemoving intermediate container 3122df8b7121Successfully built 5914eaeb88ab[INFO] Built mavendockerplugindemo[INFO] Tagging mavendockerplugindemo with 0.0.2-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 11.848 s[INFO] Finished at: 2017-12-23T02:42:11-08:00[INFO] Final Memory: 35M/84M[INFO] ------------------------------------------------------------------------
复制代码


  • 输入 docker images 命令,看到的信息如下,镜像已经在本地了:

REPOSITORY              TAG                 IMAGE ID            CREATED              SIZEmavendockerplugindemo   0.0.2-SNAPSHOT      5914eaeb88ab        About a minute ago   658 MBmavendockerplugindemo   latest              5914eaeb88ab        About a minute ago   658 MBmavendockerplugindemo   0.0.1-SNAPSHOT      ad342e51021e        2 hours ago          658 MB
复制代码

验证第二种方式构建的镜像

  • 执行以下命令,使用刚刚构建的镜像创建一个容器:

docker run --name demo002 -p 8080:8080 mavendockerplugindemo:0.0.2-SNAPSHOT
复制代码


  • 再去 windows 的浏览器上访问 http://192.168.119.155:8080/, 可以看到和之前一样的信息,如果您不放心,也可以自己修改工程的 controller 源码,再构建验证是否生效;

  • 至此,我们通过两种方式构建本地 docker 镜像的实战就结束了,但镜像停留在本地,只能手工 push 到公有或者私有仓库才能给其他人使用,在下一章我们就来体验 docker-maven-plugin 插件的推送能力,将本地镜像推送到私服,这样就能将项目编译构建、镜像构建、镜像推送等环节集成在一次构建中完成;

欢迎关注 InfoQ:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

发布于: 刚刚阅读数: 2
用户头像

搜索"程序员欣宸",一起畅游Java宇宙 2018.04.19 加入

前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos

评论

发布
暂无评论
maven构建docker镜像三部曲之二:编码和构建镜像_Docker_程序员欣宸_InfoQ写作社区