1. 程式人生 > >在Docker容器中執行Spring Boot應用

在Docker容器中執行Spring Boot應用

Spring Boot簡化了Spring應用的開發過程,遵循約定優先配置的原則提供了各類開箱即用(out-of-the-box)的框架配置。另一方面,Spring Boot還具備將程式碼直接構建為可執行jar包的能力,這個jar包是一個可以獨立執行的部署單元。基於以上特性,現在普遍認為Spring Boot提供了一種快速構造微服務(Micro-Service)的能力。

Docker與Spring Boot

Docker是一種Linux容器的實現,Linux容器是基於程序的輕量級資源隔離技術,每一個容器對應作業系統中的一個程序,但是它又會有自己的網路空間、檔案系統、PID等。Docker除了實現Linux容器,還使得容器具有“社會化”的功能,使用者可以將容器映象釋出在

Docker Hub與其他開發者共享、協作。安裝Docker的教程請參考官方文件

Spring Boot應用通常被構建為一個可單獨執行的jar包,通過java -jar ...執行,但是框架本身並沒有提供以服務形式執行在後臺的方法,通常需要藉助Systemd, Supervisord等程序管理工具來實現。另一方面,雖然應用執行環境非常的簡單,但是將他們容器化為Docker容器映象並執行,對於自動化部署、運維都是非常有利的。

本文將以一個最簡單的Spring Boot開發的Web應用為例,講解如何將其容器化執行。本文的重點是構建Docker映象、執行Docker容器,關於Spring Boot開發Web應用可以參考

Spring Boot應用開發

構建並Spring Boot應用

在應用程式碼編寫完成後,可以直接將其打包並執行:

  • Maven: mvn package && java -jar target/spring-boot-docker-0.1.0.jar
  • Gradle: gradle build && java -jar build/libs/gs-spring-boot-docker-0.1.0.jar

Dockerfile構建映象

Docker提供了Dockerfile格式的檔案來構建應用映象,現在開始建立一個Spring Boot應用的Dockerfile:

FROM java:8
VOLUME /tmp
ADD spring-boot-docker-0.1.0.jar app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

java:8是指Docker Hub上官方提供的java映象,版本號是8也就是jdk1.8,有了這個基礎映象後,Dockerfile可以通過FROM指令直接獲取它的狀態——也就是在容器中java是已經安裝的,接下來通過自定義的命令來執行Spring Boot應用:

  • VOLUME /tmp建立/tmp目錄並持久化到Docker資料資料夾,因為Spring Boot使用的內嵌Tomcat容器預設使用/tmp作為工作目錄
  • ADD spring-boot-docker-0.1.0.jar app.jar 將應用jar包複製到/app.jar
  • ENTRYPOINT表示容器執行後預設執行的命令

Dockerfile非常的簡單,編輯完成後執行docker構建映象命令:

docker build -t tmy/spring-boot-app .

然後執行Docker容器:

docker run -d -p 8080:8080 --name sample-app tmy/spring-boot-app

其中-d表示後臺執行容器,這也就自然地解決的Spring Boot不支援後臺執行應用程式的問題。-p 8080:8080表示將容器內部的8080埠對映到宿主機器的8080埠,這樣就可以通過宿主機器直接訪問應用。--name sample-app給容器取一個容易記住的名字方便日後管理。

使用Maven/Gradle建立Docker映象

為了方便Java開發者建立Docker映象,Maven/Gradle都提供了響應的外掛。

Maven

<properties>
      <docker.image.prefix>springio</docker.image.prefix>
</properties>
<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>0.2.3</version>
            <configuration>
                <imageName>${docker.image.prefix}/${project.artifactId}</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>
    </plugins>
</build>

上述pom.xml包含了docker-maven-plugin的配置:

  • imageName指定了映象的名字
  • dockerDirectory指定Dockerfile的位置
  • resources是指那些需要和Dockerfile放在一起,在構建映象時使用的檔案,一般應用jar包需要納入

經過以上配置後,執行下列命令可以在本地Docker中建立一個映象:

$ mvn package docker:build

Gradle

Gradle同樣也有支援Docker的外掛:

buildscript {
    ...
    dependencies {
        ...
        classpath('se.transmode.gradle:gradle-docker:1.2')
    }
}

group = 'springio'

...
apply plugin: 'docker'

task buildDocker(type: Docker, dependsOn: build) {
  push = true
  applicationName = jar.baseName
  dockerfile = file('src/main/docker/Dockerfile')
  doFirst {
    copy {
      from jar
      into stageDir
    }
  }
}

上述配置和Maven基本類似,執行以下命令構建映象:

$ gradle build buildDocker