你想要的Docker自动部署Spring Boot就在这

你想要的Docker自动部署Spring Boot就在这

 

简介

Spring Boot的快速开发特性,正受越来越多Java开发者的欢迎,配合supervisord可以轻松使其作为一个独立的服务运行。而随着Docker的流行,其轻量级、进程级、资源隔离等特性,使Spring Boot的部署、运行更加灵活,若将其打包成Docker镜像可以真正做到“一次打包,到处运行”,有效的解决了开发、测试、预生产、生产等环境的差异。

下面我们就从Docker手动、自动部署Spring Boot项目来讲解下,Docker是如何轻松部署的。因此你想要的Docker自动部署Spring Boot就在这了。

我们正式开始讲解吧。

手动构建spring boot应用

此部分通过直接手动打包、Docker手动部署Spring Boot,运行helloworld项目。

helloworld应用

  1. 创建spring boot工程

使用IntelliJ IDEA的“Spring Assistant”插件创建spring web项目

Group id: com.docker

Artifact id: hellworld

Project name: helloworld

Package name: com.docker.helloworld

  1. 创建HelloworldController
vim HelloworldControllerpackage com.docker.helloworld;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloworldController {        private static final Logger logger= LoggerFactory.getLogger(HelloworldController.class);    @RequestMapping("/")    public String index(){        return "Hello world";    }
  1. 编译运行
mvn clean package && java -jar target/helloworld-0.0.1-SNAPSHOT.jar

maven手动打包后并运行jar包,通过localhost:8080可以直接hellworld项目了,下面手动将jar包放到Docker中运行。

docker构建镜像

  1. Dockerfile
#基础镜像java 1.8From java#匿名数据卷,在启动容器时忘记挂载数据卷,会自动挂载到匿名卷VOLUMN /tmpARG JAR_FILE=target/*.jarCOPY ${JAR_FILE} helloworld.jarENTRYPOINT ["java","-jar","/helloworld.jar"]
  1. 构建镜像并运行容器
#从dockerfile构建镜像[root@test]# docker build -t docker/helloworld .#docker/helloworld就是我们构建的新镜像[root@test]# docker image lsREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEdocker/helloworld   latest              75c3d26e3c57        8 minutes ago       661MB#运行容器[root@test]# docker run -d -p 8080:8080 --name hellworld docker/helloworld#查看镜像[root@test]# docker ps -lCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS                                        NAMESfeb8b6ef9941        docker/helloworld   "java -jar /hellowor…"   8 minutes ago       Up 8 minutes                 0.0.0.0:8080->8080/tcp                       hellworld

利用Dockerfile构建一个运行helloworld的镜像,基与这个镜像启动容器后,我们可以通过localhost:8080访问了helloworld了。

以上两步其实就是Docker自动部署Spring Boot主要完成的两个步骤,整个过程不是手动完成,而下面要讲的是通过maven提供的插件自动完成build、tag、push镜像。

自动构建Spring Boot

配置maven插件

maven插件docker-maven-plugin可以打包应用并将构建docker镜像,推送到docker仓库。

#添加docker-maven-plugin到pom.xml#版本已经使用新版本<plugin><groupId>com.spotify</groupId><artifactId>docker-maven-plugin</artifactId><version>1.2.2</version><configuration><imageName>docker/helloworld</imageName><dockerDirectory>src/main/docker</dockerDirectory><resources><resource><targetPath>/</targetPath><directory>${project.build.directory}</directory><include>${project.build.finalName}.jar</include></resource></resources></configuration></plugin>

其中:

  1. <imageName> 是构建镜像的名称;
  2. <dockerDirectory>是Dockerfile位置,最好是只有Dockerfile,因为在mvn打包时此目录下的所有文件包括Dockerfile将会被copy到${project.build.directory}/docker目录下,此目录一般是target/docker目录;
  3. <resource>作用是将${project.build.directory}目录下的${project.build.finalName}.jar,复制到${project.build.directory}/docker目录下;如:将target/helloworld-0.0.1-SNAPSHOT.jar 文件复制到target/docker/下;

打包构建

  1. maven可以直接将应用打包成docker镜像
[root@test]# mvn clean package docker:build[INFO] --- docker-maven-plugin:1.2.2:build (default-cli) @ helloworld ---[INFO] Using authentication suppliers: [ConfigFileRegistryAuthSupplier][INFO] Copying /home/yanggd/java/docker/helloworld/target/helloworld-0.0.1-SNAPSHOT.jar -> /home/yanggd/java/docker/helloworld/target/docker/helloworld-0.0.1-SNAPSHOT.jar[INFO] Copying src/main/docker/Dockerfile -> /home/yanggd/java/docker/helloworld/target/docker/Dockerfile[INFO] Building image docker/helloworldStep 1/5 : From javaPulling from library/java5040bd298390: Pull complete fce5728aad85: Pull complete 76610ec20bf5: Pull complete 60170fec2151: Pull complete e98f73de8f0d: Pull complete 11f7af24ed9c: Pull complete 49e2d6393f32: Pull complete bb9cdec9c7f3: Pull complete Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9dStatus: Downloaded newer image for java:latest ---> d23bdf5b1b1bStep 2/5 : VOLUME /tmp ---> Running in fa47a820cd54Removing intermediate container fa47a820cd54 ---> 434e44760301Step 3/5 : ARG JAR_FILE=*.jar ---> Running in 3e0266b2cb16Removing intermediate container 3e0266b2cb16 ---> aa3be3ab4dafStep 4/5 : COPY ${JAR_FILE} helloworld.jar ---> 73cfed161b79Step 5/5 : ENTRYPOINT ["java","-jar","/helloworld.jar"] ---> Running in 1e6d6ec86542Removing intermediate container 1e6d6ec86542 ---> 9027adc2d0a4ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}Successfully built 9027adc2d0a4Successfully tagged docker/helloworld:latest

其中:第Step 4/5、Step 5/5可以看到copy过程,剩下为从Dockerfile构建镜像过程。

  1. 查看并运行打包后的镜像
#查看镜像[root@test]# docker image lsREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEdocker/helloworld   latest              9027adc2d0a4        About an hour ago   661MB#运行docker run -d -p 8080:8080  --name helloworld docker/helloworld

从以上看出此镜像是没有tag,通过以下方式添加tag:

#在pom.xml的configuration段中添加如下:<imageTags><imageTag>test</imageTag></imageTags>或者#在命令行直接打tagmvn clean package docker:build -DdockerImageTags=v1#构建完成后,同一image_id 有不同的tag[root@test]# docker image lsREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEdocker/helloworld   v1                  6f3b482d2b78        10 seconds ago      661MBdocker/helloworld   latest              6f3b482d2b78        10 seconds ago      661MBdocker/helloworld   test                6f3b482d2b78        10 seconds ago      661MB

如上,我们通过两种方式给镜像添加了test和v1两个tag。了解如何添加tag后,就会明白后面的push镜像的配置。

以上是通过maven自动构建镜像并添加tag,但是还没有完成自动推送远程仓库,咱们将继续讲解。

推送镜像到远程仓库阿里云镜像库

  1. 创建仓库

在阿里云容器镜像服务创建仓库

registry.cn-qingdao.aliyuncs.com/test/test
  1. maven配置镜像库认证

在maven配置文件中指定远程的镜像仓库

vim settings.xml#servers块中插入<server>  <id>docker-aliyun</id>  #阿里云开通的账户名  <username>xxxx</username>  #开通镜像服务的密码,不是阿里云登录密码  <password>xxxxx</password>  <configuration>    #阿里云绑定邮箱    <email>xxxxx</email>  </configuration></server>
  1. pom.xml配置

配置pom.xml是因为这些都是maven自动构建、推送镜像的基础参数。

<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>com.spotify</groupId><artifactId>docker-maven-plugin</artifactId><version>1.2.2</version><configuration>    <!--镜像名称要于阿里云镜像仓库对应,否则无法push到阿里云仓库-->    <!--功能等于docker tag docker/helloworld registry.cn-qingdao.aliyuncs.com/test/test--><imageName>registry.cn-qingdao.aliyuncs.com/test/test</imageName><dockerDirectory>src/main/docker</dockerDirectory><resources><resource><targetPath>/</targetPath><directory>${project.build.directory}</directory><include>${project.build.finalName}.jar</include></resource></resources><!--一定与mvn的id对应--><serverId>docker-aliyun</serverId><registryUrl>registry.cn-qingdao.aliyuncs.com/test/test</registryUrl></configuration></plugin></plugins></build>
  1. 构建并push
#构建,只推送tag为v3至远程仓库[root@test]# mvn clean package docker:build -DdockerImageTags=v3 -DpushImageTag[root@test]# docker image lsREPOSITORY                                              TAG                 IMAGE ID            CREATED              SIZEregistry.cn-qingdao.aliyuncs.com/test/test   latest              08d5a09985a1        20 seconds ago       661MBregistry.cn-qingdao.aliyuncs.com/test/test   v3                  08d5a09985a1        20 seconds ago       661MB

此处需要注意:

#若不加-DdockerImageTags=v3 ,会将所有构建的镜像(v3及latest)都上传。mvn clean package docker:build -DpushImageTag#若不加-DpushImageTag,只会构建镜像并tag 为v3,但不会push。mvn clean package docker:build -DdockerImageTags=v3

最后查看下阿里云的镜像库:

 

整个推送的过程关键点在远程仓库的认证及将镜像添加tag与远程镜像一致。

以上为maven 构建、tag、推送的整个步骤,前提是要保证pom.xml中的配置信息没有错误。其实我们还可以将Docker的构建过程绑定到maven的各个阶段,我们再来深入讲解下。

绑定Docker命令到Maven各个阶段

Docker 构建过程为 build、tag、push,其中build、tag对应mvn的package阶段,push对应mvn的deploy。通过将docker命令绑定到mvn的各个阶段,我们可以通过mvn deploy实现构建并push的过程。

补充:

  1. package阶段实现项目编译、单元测试、打包功能,但没有把打好的可执行jar包(war包或其它形式的包)部署到本地maven仓库和远程maven私服仓库;
  2. install阶段实现项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库,但没有布署到远程maven私服仓库;
  3. deploy阶段实现项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)部署到本地maven仓库和远程maven私服仓库;

1.pom.xml配置插件

<!--一定添加maven-deploy-plugin,通过skip跳过artifact仓库--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-deploy-plugin</artifactId><configuration><skip>true</skip></configuration></plugin><plugin><groupId>com.spotify</groupId><artifactId>docker-maven-plugin</artifactId><version>1.2.2</version><configuration><imageName>registry.cn-qingdao.aliyuncs.com/test/test</imageName><dockerDirectory>src/main/docker</dockerDirectory><resources><resource><targetPath>/</targetPath><directory>${project.build.directory}</directory><include>${project.build.finalName}.jar</include></resource></resources><imageTags><imageTag>${project.version}</imageTag></imageTags><serverId>docker-aliyun</serverId><pushImage>true</pushImage><registryUrl>registry.cn-qingdao.aliyuncs.com/test/test</registryUrl></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>registry.cn-qingdao.aliyuncs.com/test/test:${project.version}</image><newName>registry.cn-qingdao.aliyuncs.com/test/test:${project.version}</newName></configuration></execution><execution><id>push-image</id><phase>deploy</phase><goals><goal>push</goal></goals><configuration><imageName>registry.cn-qingdao.aliyuncs.com/test/test:${project.version}</imageName></configuration></execution></executions></plugin>

注意:一定要通过maven-deploy-plugin设置skip,否则mvn deploy 推送时报错:

Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter

2.执行命令

#构建、tag 不推送mvn clean package#构建、tag及推送到远程仓库mvn clean deploy #跳过整个过程,不执行实际命令,可用测试流程是否正常mvn clean deploy -DskipDocker#跳过构建mvn clean -DskipDockerBuild#跳过tagmvn clean -DskipDockerTag#跳过pushmvn clean -DskipDockerPush

注意:

  1. 经测试发现,实际<goal>tag</goal>阶段并不会进行tag,而是在<imageName>registry.cn-qingdao.aliyuncs.com/test/test</imageName>进行tag,如果你的imageName设置不正确,则不会推送到自定义仓库,而是默认的官方仓库
  2. 此方式会将镜像的所有tag 版本,如v3和latest都会推送到远程仓库;

通过对比,"docker命令绑定maven各阶段"方式不太灵活,因为这会将镜像所有tag进行推送;而使用不绑定到maven阶段的可以自由设置推送到远程仓库的tag,这点更灵活。我们需要根据实际情况自由选择。

总结

通过以上讲解,我们应该知道Docker部署Spring Boot的原理及细节,剩下只需要在客户端直接运行就可以,真正做到“一次打包,到处运行”。如果你完全掌握那么Docker算是入门了。但是这对于Docker的深入应用还远远不够,在实际过程中我们还需要考虑以下问题:

  1. Spring Boot应用的运行时数据、日志文件的持久化;
  2. 镜像命令、目录问题、私有镜像库等的配合使用;
  3. 流水线操作实现测试、版本发布等;
  4. Docker 健康检查等;

这些需要我们通过不断实践,完善开发、运维、测试等在应用中的需求才能做到的,因此让我们行动起来吧。

posted @ 2022-08-17 09:33  菜菜聊架构  阅读(324)  评论(0编辑  收藏  举报