使用Docker構建、發布Spring Boot應用

1. 簡介

Docker 是一個開源的應用容器引擎,讓開發人員可以將應用打包部署到一個可移植的容器中,然后發布到任何流行的Linux服務器上,容器是完全使用沙箱機制,相互之間不會有任何接口。

一個完整的Docker有以下幾個部分組成:

  1. Docker Client 客戶端
  2. Docker Daemon 守護進程
  3. Docker Image 鏡像
  4. Docker Container 容器

2. 準備工作

為了通過Docker來構建與部署Spring Boot應用, 我們需要有一個安裝過 Docker 環境的服務器來打包 Spring Boot 項目, 因此在進行項目構建時, 需要安裝Java、Maven和Docker的應用環境,建議使用Linux系統來構建Docker鏡像。 Java與Maven環境安裝與配置在這就不詳細介紹了,Docker環境安裝與配置可以參考之前寫過的文章《Docker容器安裝與部署》。

環境配置

  • Java版本: JDK1.8+
  • Maven版本: Maven3.0+
  • Docker版本: Docker 17.06+

3. 構建Spring Boot項目

1. 配置Maven項目依賴文件pom.xml

  • 添加Spring Boot項目依賴
 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0</version>
        <relativePath/>
</parent>
  • 添加Spring Boot項目相關的依賴包
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Java Mail -->
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.6.1</version>
        </dependency>
</dependencies>
  • 創建Controller, 提供服務接口, 此處提供一個測試接口
@RestController
public class HelloController {
    
    @RequestMapping("/sayHello")
    public String sayHello() {
        return "Hello Spring Boot!";
    }
}
  • 創建Spring Boot啟動類
@SpringBootApplication
public class HelloApplication {

    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

添加完畢后啟動項目,啟動成功后瀏覽器訪問:http://localhost:8080/sayHello,調用接口頁面返回:Hello Spring Boot!,說明 Spring Boot 項目工作正常。

4. Spring Boot項目中添加Docker構建組件

支持Spring Boot項目Docker容器構建的組件有許多個, 此處選擇com.spotify:docker-maven-plugin組件進行構建。

  • 修改pom.xml文件, 添加Docker編譯支持組件
<properties>
      <docker.image.prefix>myProject</docker.image.prefix>
</properties>
<build>
      <plugins>
          <!-- Spring Boot Build Plugin -->
          <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
          <!-- Docker maven plugin -->
          <plugin>
              <groupId>com.spotify</groupId>
              <artifactId>docker-maven-plugin</artifactId>
              <version>1.2.0</version>
              <configuration>
                  <imageName>${docker.image.prefix}/${project.artifactId}:${project.version}</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>
          <!-- Docker maven plugin -->
      </plugins>
</build>

說明 :

  1. ${docker.image.prefix}為pom文件中properties中添加的配置;
  2. ${project.artifactId}為pom文件中的artifactId屬性,${project.version}為pom文件中的version屬性;
  3. dockerDirectory屬性配置dockerfile文件的存放路徑/src/main/docker
  4. resources屬性中配置復制 jar 包到 docker 容器指定目錄配置,將target下編譯的Jar包復制到docker目錄下。

我們也可以通過spotify的docker-maven-plugin組件配置, 自動創建Docker鏡像,繞過下面創建Dockerfile的步驟, 直接生成Docker鏡像:

<properties>
      <docker.image.prefix>myProject</docker.image.prefix>
</properties>
<build>
      <plugins>
          <!-- Spring Boot Build Plugin -->
          <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
          <!-- Docker maven plugin -->
          <plugin>
              <groupId>com.spotify</groupId>
              <artifactId>docker-maven-plugin</artifactId>
              <version>1.2.0</version>
              <configuration>
                  <imageName>${docker.image.prefix}/${project.artifactId}:${project.version}</imageName>
                  <baseImage>docker.io/cemmersb/centos-jdk8:latest</baseImage>
                  <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>
          <!-- Docker maven plugin -->
      </plugins>
</build>

說明:

  1. 使用baseImage屬性配置Docker容器依賴的基礎鏡像信息;
  2. 使用entryPoint屬性配置Docker容器的入口命令。
  • src/main/docker下創建Dockerfile
FROM docker.io/cemmersb/centos-jdk8:latest
MAINTAINER garyond
VOLUME /tmp
ADD hello-service:0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

關于Dockerfile的相關命令可以參考我的文章《使用Dockerfile構建Docker鏡像》, 這里我就不詳細講解了。

  • 編譯項目, 進行Docker鏡像打包, 執行命令mvn clean package docker:build
$ mvn clean package docker:build
...
Step 1/5 : FROM docker.io/cemmersb/centos-jdk8:latest
 ---> ccba23a213f2
Step 2/5 : MAINTAINER zhangjiayang <zhangjiayang@sczq.com.cn>
 ---> 0de52ae244d4
Step 3/5 : VOLUME /tmp
 ---> 3d25b5f60bb8
Step 4/5 : ADD hello-service-0.0.1-SNAPSHOT.jar app.jar
 ---> a02fcec9904c
Step 5/5 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
 ---> Running in a5cf7c699a3f
Removing intermediate container a5cf7c699a3f
 ---> 2177684b649d
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built 2177684b649d
Successfully tagged hello-service:0.0.1-SNAPSHOT
...

由于Docker構建時需要下載基礎鏡像信息, 所以過程會比較長, 所以我只粘貼了最后一部分編譯的信息。編譯完成后, 查看主機的鏡像信息。

$ docker images
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
hello-service                    0.0.1-SNAPSHOT      2177684b649d        13 minutes ago      875MB
rabbitmq                         3-management        75472a5c510b        2 months ago        149MB
cemmersb/centos-jdk8             latest              ccba23a213f2        3 years ago         858MB
  • Docker鏡像生成后, 運行Docker容器
$ docker run -d -p 8080:8080 hello-service:0.0.1-SNAPSHOT

通過docker ps命令查詢Docker容器是否正常啟動

$ docker ps

容器成功啟動后,打開瀏覽器訪問:http://localhost:8080/sayHello,調用接口頁面返回:Hello Spring Boot!,說明 Spring Boot 項目Docker容器工作正常。

5. 構建Spring Boot多模塊依賴工程

由于Spring Boot項目開發中經常會遇見多模塊的應用, 比如下面有一個應用sword, 應用中包含以下幾個模塊, 其中需要部署三個應用sword-api、sword-job、sword-admin

  • sword-common 公共模塊(基礎依賴)
  • sword-util 常用工具模塊(基礎依賴)
  • sword-api 接口模塊(獨立部署)
  • sword-job 應用采集模塊(獨立部署)
  • sword-admin 管理后臺模塊(獨立部署)

5.1 準備工作

  • 配置總體項目POM
<?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.garyond</groupId>  
    <artifactId>sword</artifactId>  
    <version>2.0.0</version>  
    <packaging>pom</packaging>  
  
    <modules>  
        <module>sword-common</module> <!--核心業務 -->  
        <module>sword-admin</module><!-- 后臺 -->  
        <module>sword-api</module><!-- API -->
        <module>sword-job</module><!-- 定時采集程序 -->  
        <module>sword-util</module><!-- 常用工具 -->  
    </modules>  
  
    <parent>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-parent</artifactId>  
        <version>2.0.4.RELEASE</version>  
        <relativePath/> <!-- lookup parent from repository -->  
    </parent>  
      
</project>  
  • 配置sword-common等基礎依賴模塊
<?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>  
  
    <artifactId>sword-common</artifactId>  
    <packaging>jar</packaging>  
  
    <parent>  
        <groupId>com.garyod</groupId>  
        <artifactId>sword</artifactId>  
        <version>2.0.0</version>  
        <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->  
    </parent>  
  
    <properties>  
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
        <java.version>1.8</java.version>  
        <relativePath/>  
    </properties>  
  
    <dependencies>  
        ......  
    </dependencies>  
  
    <build>  
        <plugins>  
            <plugin>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-maven-plugin</artifactId>  
                <configuration>  
                    <classifier>exec</classifier>  
                </configuration>  
            </plugin>           
        </plugins>  
    </build>  
  
</project>  
  • 配置sword-api、sword-admin等應用模塊
<?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>  
  
    <artifactId>sword-api</artifactId>  
    <packaging>jar</packaging>  
  
    <parent>  
        <groupId>com.garyond</groupId>  
        <artifactId>sword</artifactId>  
        <version>2.0.0</version>  
        <relativePath>../pom.xml</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>  
        ......  
    </dependencies>  
  
    <build>  
        <plugins>  
            <plugin>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-maven-plugin</artifactId>  
                <configuration>  
                    <executable>true</executable>  
                </configuration>  
            </plugin>  
              
            <!-- Docker maven plugin -->  
            <plugin>  
                <groupId>com.spotify</groupId>  
                <artifactId>docker-maven-plugin</artifactId>  
                <version>1.2.0</version>  
                <configuration>  
                    <imageName>${project.groupId}/${project.artifactId}:${project.version}</imageName>  
                    <baseImage>java:8</baseImage>
                    <maintainer>garyond</maintainer>
                    <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>  
            <!-- Docker maven plugin -->  
        </plugins>  
    </build>  
</project>  

5.2 應用部署

  1. 進入父工程(sword)pom文件所在目錄,打包編譯,將依賴包放至本地倉庫
mvn clean install package -Dmaven.test.skip
  1. 分別進入各模塊(sword-api/sword-admin/sword-job)目錄,使用 Docker構建鏡像
mvn package docker:build -Dmaven.test.skip
  1. 運行Docker容器
docker run -d -p 8080:8080 --name=sword-admin sword-admin:2.0.0
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內容