你想要的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
<code>vim HelloworldController
package com.docker.helloworld;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloworldController {
    
    private static final Logger logger= LoggerFactory.getLogger(HelloworldController.class);
    @RequestMapping("/")
    public String index(){
        return "Hello world";
    }/<code>
  1. 編譯運行
<code>mvn clean package && java -jar target/helloworld-0.0.1-SNAPSHOT.jar/<code>

maven手動打包後並運行jar包,通過localhost:8080可以直接hellworld項目了,下面手動將jar包放到Docker中運行。

docker構建鏡像

  1. Dockerfile
<code>#基礎鏡像java 1.8
From java
#匿名數據卷,在啟動容器時忘記掛載數據卷,會自動掛載到匿名卷
VOLUMN /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} helloworld.jar
ENTRYPOINT ["java","-jar","/helloworld.jar"]/<code>
  1. 構建鏡像並運行容器
<code>#從dockerfile構建鏡像
[root@test]# docker build -t docker/helloworld .

#docker/helloworld就是我們構建的新鏡像
[root@test]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker/helloworld   latest              75c3d26e3c57        8 minutes ago       661MB

#運行容器
[root@test]# docker run -d -p 8080:8080 --name hellworld docker/helloworld
#查看鏡像
[root@test]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS                                        NAMES
feb8b6ef9941        docker/helloworld   "java -jar /hellowor…"   8 minutes ago       Up 8 minutes                 0.0.0.0:8080->8080/tcp                       hellworld/<code>

利用Dockerfile構建一個運行helloworld的鏡像,基與這個鏡像啟動容器後,我們可以通過localhost:8080訪問了helloworld了。

以上兩步其實就是Docker自動部署Spring Boot主要完成的兩個步驟,整個過程不是手動完成,而下面要講的是通過maven提供的插件自動完成build、tag、push鏡像。

自動構建Spring Boot

配置maven插件

maven插件docker-maven-plugin可以打包應用並將構建docker鏡像,推送到docker倉庫。

<code>#添加docker-maven-plugin到pom.xml
#版本已經使用新版本

	com.spotify
	docker-maven-plugin
	1.2.2
	
		docker/helloworld
		src/main/docker
		
			
				/
				${project.build.directory}
				${project.build.finalName}.jar
			
		
	
/<code>

其中:

  1. 是構建鏡像的名稱;
  2. 是Dockerfile位置,最好是隻有Dockerfile,因為在mvn打包時此目錄下的所有文件包括Dockerfile將會被copy到${project.build.directory}/docker目錄下,此目錄一般是target/docker目錄;
  3. 作用是將${project.build.directory}目錄下的${project.build.finalName}.jar,複製到${project.build.directory}/docker目錄下;如:將target/helloworld-0.0.1-SNAPSHOT.jar 文件複製到target/docker/下;

打包構建

  1. maven可以直接將應用打包成docker鏡像
<code>[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/helloworld
Step 1/5 : From java

Pulling from library/java
5040bd298390: 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:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
Status: Downloaded newer image for java:latest
 ---> d23bdf5b1b1b
Step 2/5 : VOLUME /tmp

 ---> Running in fa47a820cd54
Removing intermediate container fa47a820cd54
 ---> 434e44760301
Step 3/5 : ARG JAR_FILE=*.jar

 ---> Running in 3e0266b2cb16
Removing intermediate container 3e0266b2cb16
 ---> aa3be3ab4daf
Step 4/5 : COPY ${JAR_FILE} helloworld.jar

 ---> 73cfed161b79
Step 5/5 : ENTRYPOINT ["java","-jar","/helloworld.jar"]

 ---> Running in 1e6d6ec86542
Removing intermediate container 1e6d6ec86542
 ---> 9027adc2d0a4
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built 9027adc2d0a4
Successfully tagged docker/helloworld:latest
/<code>

其中:第Step 4/5、Step 5/5可以看到copy過程,剩下為從Dockerfile構建鏡像過程。

  1. 查看並運行打包後的鏡像
<code>#查看鏡像
[root@test]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker/helloworld   latest              9027adc2d0a4        About an hour ago   661MB
#運行
docker run -d -p 8080:8080  --name helloworld docker/helloworld/<code>

從以上看出此鏡像是沒有tag,通過以下方式添加tag:

<code>#在pom.xml的configuration段中添加如下:


	test


或者
#在命令行直接打tag
mvn clean package docker:build -DdockerImageTags=v1

#構建完成後,同一image_id 有不同的tag
[root@test]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker/helloworld   v1                  6f3b482d2b78        10 seconds ago      661MB
docker/helloworld   latest              6f3b482d2b78        10 seconds ago      661MB
docker/helloworld   test                6f3b482d2b78        10 seconds ago      661MB/<code>

如上,我們通過兩種方式給鏡像添加了test和v1兩個tag。瞭解如何添加tag後,就會明白後面的push鏡像的配置。

以上是通過maven自動構建鏡像並添加tag,但是還沒有完成自動推送遠程倉庫,咱們將繼續講解。

推送鏡像到遠程倉庫阿里雲鏡像庫

  1. 創建倉庫

在阿里雲容器鏡像服務創建倉庫

<code>registry.cn-qingdao.aliyuncs.com/test/test/<code>
  1. maven配置鏡像庫認證

在maven配置文件中指定遠程的鏡像倉庫

<code>vim settings.xml
#servers塊中插入

  docker-aliyun
  #阿里雲開通的賬戶名
  xxxx
  #開通鏡像服務的密碼,不是阿里雲登錄密碼
  xxxxx
  
    #阿里雲綁定郵箱
    xxxxx
  
/<code>
  1. pom.xml配置

配置pom.xml是因為這些都是maven自動構建、推送鏡像的基礎參數。

<code>
	
		
			org.springframework.boot
			spring-boot-maven-plugin
		
		
			com.spotify
			docker-maven-plugin
			1.2.2
			
			     
			     
				registry.cn-qingdao.aliyuncs.com/test/test
				src/main/docker
				
					
						/
						${project.build.directory}
						${project.build.finalName}.jar
					
				
				 
				docker-aliyun
				registry.cn-qingdao.aliyuncs.com/test/test
			
		
	
/<code>
  1. 構建並push
<code>#構建,只推送tag為v3至遠程倉庫
[root@test]# mvn clean package docker:build -DdockerImageTags=v3 -DpushImageTag
[root@test]# docker image ls
REPOSITORY                                              TAG                 IMAGE ID            CREATED              SIZE
registry.cn-qingdao.aliyuncs.com/test/test   latest              08d5a09985a1        20 seconds ago       661MB
registry.cn-qingdao.aliyuncs.com/test/test   v3                  08d5a09985a1        20 seconds ago       661MB/<code> 

此處需要注意:

<code>#若不加-DdockerImageTags=v3 ,會將所有構建的鏡像(v3及latest)都上傳。
mvn clean package docker:build -DpushImageTag
#若不加-DpushImageTag,只會構建鏡像並tag 為v3,但不會push。
mvn clean package docker:build -DdockerImageTags=v3/<code>

最後查看下阿里雲的鏡像庫:


你想要的Docker自動部署Spring Boot就在這

整個推送的過程關鍵點在遠程倉庫的認證及將鏡像添加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配置插件

<code> 

	org.apache.maven.plugins
	maven-deploy-plugin
	
		true
	


	com.spotify
	docker-maven-plugin
	1.2.2
	
		registry.cn-qingdao.aliyuncs.com/test/test
		src/main/docker
		
			
				/
				${project.build.directory}
				${project.build.finalName}.jar
			
		
		
			${project.version}
		
		docker-aliyun
		true
		registry.cn-qingdao.aliyuncs.com/test/test
	
	
		
			build-image
			package
			
				build
			
		
		
			tag-image
			package
			
				tag
			
			
				
				registry.cn-qingdao.aliyuncs.com/test/test:${project.version}
			
		
		
			push-image
			deploy
			
				push
			
			
				registry.cn-qingdao.aliyuncs.com/test/test:${project.version}
			
		
	
/<code>

注意:一定要通過maven-deploy-plugin設置skip,否則mvn deploy 推送時報錯:

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

2.執行命令

<code>#構建、tag 不推送
mvn clean package
#構建、tag及推送到遠程倉庫
mvn clean deploy 
#跳過整個過程,不執行實際命令,可用測試流程是否正常
mvn clean deploy -DskipDocker
#跳過構建
mvn clean -DskipDockerBuild
#跳過tag
mvn clean -DskipDockerTag
#跳過push
mvn clean -DskipDockerPush/<code>

注意:

  1. 經測試發現,實際tag階段並不會進行tag,而是在registry.cn-qingdao.aliyuncs.com/test/test進行tag,如果你的imageName設置不正確,則不會推送到自定義倉庫,而是默認的官方倉庫
  2. 此方式會將鏡像的所有tag 版本,如v3和latest都會推送到遠程倉庫;

通過對比,"docker命令綁定maven各階段"方式不太靈活,因為這會將鏡像所有tag進行推送;而使用不綁定到maven階段的可以自由設置推送到遠程倉庫的tag,這點更靈活。我們需要根據實際情況自由選擇。

總結

通過以上講解,我們應該知道Docker部署Spring Boot的原理及細節,剩下只需要在客戶端直接運行就可以,真正做到“一次打包,到處運行”。如果你完全掌握那麼Docker算是入門了。但是這對於Docker的深入應用還遠遠不夠,在實際過程中我們還需要考慮以下問題:

  1. Spring Boot應用的運行時數據、日誌文件的持久化;
  2. 鏡像命令、目錄問題、私有鏡像庫等的配合使用;
  3. 流水線操作實現測試、版本發佈等;
  4. Docker 健康檢查等;

這些需要我們通過不斷實踐,完善開發、運維、測試等在應用中的需求才能做到的,因此讓我們行動起來吧。


分享到:


相關文章: