今天学习一下将 Spring Boot 项目一键打包到远程 Docker 容器中,然后通过运行一个镜像的方式来启动一个 Spring Boot 项目。
首先准备Docker,我这里用阿里的服务器演示
-
首先需要在 CentOS7 上安装好 Docker,这个安装方式网上很多,我就不多说了
-
Docker 安装成功之后,我们首先需要修改 Docker 配置,开启允许远程访问 Docker 的功能
vi /usr/lib/systemd/system/docker.service #编辑文件
-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock #在execStart=后面添加配置
配置完成后,保存退出,然后重启 Docker
systemctl daemon-reload
service docker restart
接下来我们使用docker-maven-plugin GitHub地址 插件自动化的方式构建镜像,该插件是基于maven插件,用来构建docker镜像,当然也可以通过在系统中配置Dockerfile的方式构建镜像。
在POM中声明构建信息
在pom.xml
中添加下面这段配置
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- docker的maven插件,官网 https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<!--将Docker命令绑定到Maven阶段,也就是使用maven的package命令打包时自动构建镜像-->
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<!--配置 Docker 的主机地址-->
<dockerHost>http://xxx.xxx.xxx.xxx:2375</dockerHost>
<imageName>${project.artifactId}:${project.version}</imageName>
<baseImage>java</baseImage>
<!--相当于Dokcerfile文件中的ENTRYPOINT ["java","-jar","/app.jar"]-->
<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>
</build>
这个插件的配置不难理解:
-
configuration 中分别配置 Docker 的主机地址,镜像的名称,镜像的 tags,其中 dockerDirectory 表示指定 Dockerfile 的位置。
-
imageName:镜像的名称,可以通过
${project.groupId}/${project.artifactId}:${project.version}
动态制定镜像名称,当然也可以在前面加上镜像地址,比如127.0.0.1:5000,以声明将构建好的镜像存储上传到自己私服 -
baseImage: 基础镜像,这里是相当于Dockerfile的FROM java
-
resources 下的配置:构建时会生成docker文件夹,这里指生成文件夹的内容来源,包含了mvn clean package 之后的target的文件和生成的jar包。
-
execution 节点中配置当执行 mvn package 的时候,顺便也执行一下 docker:build
以上配置会自动生成Dockerfile文件,可以在target/docker文件夹下看见如下图所示
注: 打包过程会有点久,因为还包含了镜像的构建,第一次打包需要下载基础镜像,会更慢
运行容器测试
可以看到我们镜像已经上传完成了,我们创建容器运行测试一下。(至于为什么这么大的话,因为里面包含Java环境)
我们在浏览器中来访问一下
上面这种方式讲述的是最简单的方式直接在pom.xml中配置的方式,很多时候,我们还是要借助Dockerfile
进行构建生成镜像的,首先我们在src/main/docker
目录下,建立文件Dockerfile文件
使用Dockerfile
要使用Dockerfile
,您必须指定dockerDirectory
元素。如果指定了 baseImage
,maintainer
,cmd
和entryPoint
元素将被忽略。的内容 dockerDirectory
将复制到中${project.build.directory}/docker
。使用resources
元素复制其他文件,例如服务的jar文件。
Dockerfile文件
FROM java
VOLUME /tmp
ADD docker_upload-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'
EXPOSE 8080
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
注:${imageName} 为pom.xml中配置的标签
命令解析:
- FROM:表示基础镜像,即运行环境
- VOLUME:一个特别指定的目录,用于存储数据,该命令的作用是在/var/lib/docker创建一个名为tmp的目录
- ADD:拷贝文件并且重命名
- RUN: 构建镜像时执行的命令
- EXPOSE: 指定于外界交互的端口
- ENTRYPOINT:容器启动时运行的命令,相当于我们在命令行中输入java -jar xxxx.jar,为了缩短 Tomcat 的启动时间,添加java.security.egd的系统属性指向/dev/urandom作为 ENTRYPOINT
pom.xml
文件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- docker的maven插件,官网 https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<!--配置 Docker 的主机地址-->
<dockerHost>http://xxx.xx.xxx.xx:2375</dockerHost>
<!-- 详见:https://github.com/spotify/docker-maven-plugin Invalid repository name ... only [a-z0-9-_.] are allowed-->
<!--端口5000为registry私有仓库的访问端口-->
<imageName>xxx.xx.xxx.xx:5000/${project.artifactId}:${project.version}</imageName>
<!-- 指定Dockerfile所在的路径 -->
<dockerDirectory>${basedir}/src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
按照上面的配置之后,可以使用如下命令生成一个镜像
mvn clean package docker:build
将生成的镜像推送到私有仓库,请指定pushImage
标签
mvn clean package docker:build -DpushImage
如果推送指定tags 的镜像,可使用pushImageTag
标签
mvn clean package docker:build -DpushImageTag
为了使上述的命令执行成功,需要在pom中配置imageTag
,可以配置多个imageTag
<build>
<plugins>
...
<plugin>
<configuration>
...
<imageTags>
<imageTag>${project.version}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
</configuration>
</plugin>
...
</plugins>
</build>
如果你想强制docker在每次新的构建上覆盖镜像tags,可配置foreceTags
<build>
<plugins>
...
<plugin>
<configuration>
...
<!-- optionally overwrite tags every time image is built with docker:build -->
<forceTags>true</forceTags>
<imageTags>
...
</imageTags>
</configuration>
</plugin>
...
</plugins>
</build>
也可以在构建的命令行上添加上镜像tags:
mvn ... docker:build -DpushImageTags -DdockerImageTags=latest -DdockerImageTags=another-tag
我使用的mvn clean package docker:build -DpushImage 命令
,不上传则使用mvn clean package docker:build 命令构建镜像
在构建成功之后进入宿主机就可以查看到已经创建的镜像,并且已经上传到私服当中