Spring Boot Docker化官方文檔

@author StormMa
@date 2017-10-12


生命不息,奮鬥不止!

Spring Boot應用Docker化

原文:Spring Boot with Docker
譯者:stormma

本教程將引導你通過建立一個Docker鏡像來運行Spring Boot應用。

你將構建什麼

Docker是一個管理工具包的Linux容器,用戶可以發佈鏡像以及使用其他開發者發佈的鏡像。Docker鏡像是一個運行集裝箱化的過程,本教程將構建一個簡單的Spring Boot應用程序。

構建之前你要準備的東西

  • 大約十五分鐘的時間
  • 一個你最喜歡的文本編輯器或者IDE
  • JDK1.8+
  • Gradle2.3+或者Maven3.0+
  • 你也可以直接將代碼導入你的IDE

如果你當前使用的系統不是Linux,那麼你需要一個虛擬機。通過安裝VirtualBox或者像mac的boot2docker等其他工具都可以滿足你的使用。
訪問VirtualBox下載地址選擇你的系統版本來下載VirtualBox,並且安裝運行起來。

當然你也需要安裝Docker(只能在64位機器上運行),有關詳細信息請參閱https://docs.docker.com/installation/#installation來安裝Docker到你的系統上。開始下一步之前,你要確認在你的shell上是否可以運行docker命令,如果你使用的是boot2docker,在運行docker命令之前你需要先啓動boot2docker。

如何完成這篇教程

像大多數的Spring系列教程 Getting Started guides,你可以從頭開始,完成每一步,也可以跳過已經熟悉的步驟。 無論哪種方式,你都可以成功。

從頭開始, 參閱使用Gradle構建.

跳過基礎部分, 執行以下操作:

  • 下載並解壓本倉庫代碼,或者使用git clone https://github.com/spring-guides/gs-spring-boot-docker.git克隆代碼庫。
  • 進入gs-spring-boot-docker/initial目錄
  • 前往創建Spring Boot應用程序

完成以上操作之後,你可以和gs-spring-boot-docker/complete代碼進行比對。

使用Gradle構建

首先你得安裝構建腳本. 你可以使用你喜歡的構建系統去構建Spring應用, 你需要的工具在下面都可以找到: GradleMaven . 如果你對GradleMaven都不熟悉,請參閱使用Gradle構建Java項目或者使用Maven構建Java項目.

創建目錄結構

在你當前項目工作目錄中,創建如下子目錄:

└── src
    └── main
        └── java
            └── hello

如在Linux系統下使用mkdir -p src/main/java/hello來創建。

創建Gradle項目文件(build.gradle)

如下是一個gradle項目文件

build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.4.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

jar {
    baseName = 'gs-spring-boot-docker'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("org.springframework.boot:spring-boot-starter-test")
}

Spring Boot gradle插件 提供了很多便捷的功能:

  • 它集中了classpath下的所有jar,並構建一個可運行的jar,這樣可以更方便地執行和發佈服務。
  • 它找到public static void main()方法並標記該類爲可執行。
  • 它提供了一個內置的依賴解析器,將應用與Spring Boot依賴的版本號進行匹配。你可以修改成你希望的版本,但它默認爲Spring Boot選擇的版本。

使用maven構建

首先你得安裝構建腳本. 你可以使用你喜歡的構建系統去構建Spring應用,你可以前往Maven官網來指導你安裝。 如果你對Maven不熟悉,請參閱使用Maven構建Java項目.

創建目錄結構

在你當前項目工作目錄中,創建如下子目錄:

└── src
    └── main
        └── java
            └── hello

如在Linux系統下使用mkdir -p src/main/java/hello來創建。

pom.xml

<?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>org.springframework</groupId>
    <artifactId>gs-spring-boot-docker</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <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>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Spring Boot maven插件 提供了很多便捷的功能:

  • 它集中了classpath下的所有jar,並構建一個可運行的jar,這樣可以更方便地執行和發佈服務。
  • 它找到public static void main()方法並標記該類爲可執行。
  • 它提供了一個內置的依賴解析器,將應用與Spring Boot依賴的版本號進行匹配。你可以修改成你希望的版本,但它默認爲Spring Boot選擇的版本。

使用你的IDE構建

創建一個Spring Boot應用程序

現在你可以創建一個簡單的Spring Boot應用程序。

src/main/java/hello/Application.java

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class Application {

    @RequestMapping("/")
    public String home() {
        return "Hello Docker World";
    }

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

}

這個類使用@SpringBootApplication註解和@RestController註解標記,在於準備使用Spring MVC來處理web請求。@RequestMapping映射/home()方法上,響應Hello Docker Worldmain()方法調SpringApplication.run()方法來啓動應用程序。

現在你可以在沒有Docker的情況下運行該應用程序。

如果你使用gradle構建的Spring Boot應用程序,執行:

./gradlew build && java -jar build/libs/gs-spring-boot-docker-0.1.0.jar

如果你使用maven構建的,執行:
./mvnw package && java -jar target/gs-spring-boot-docker-0.1.0.jar

然後訪問localhost:8080就可以看見Hello Docker World字樣。

使你的應用程序容器化

Docker有一個Dockerfile文件格式的文件,並且使用指定的鏡像作爲基礎鏡像。接下來我們去創建一個Dockerfile在Spring Boot應用程序中。

Dockerfile

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD target/gs-spring-boot-docker-0.1.0.jar app.jar
ENV JAVA_OPTS=""
ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar

這個Dockerfile很簡單,但是已經包含了你運行這個Spring Boot應用程序的所有東西並且沒有多餘的東西:僅僅只有Java和一個Jar文件。應用程序的jar文件(文件名爲app.jar)被添加到容器中,執行 ENTRYPOINT

我們增加了一個VOLUME指向”/tmp”,因爲那是Spring Boot應用程序爲Tomcat創建的默認工作目錄。作用是在你的主機”/var/lib/docker”目錄下創建一個臨時的文件,並且鏈接到容器中的”/tmp”目錄。對於簡單程序這一步是可選的,但是對於其他想要真實寫入文件系統的Spring Boot應用程序又是必選的。

我們增加了一個指向”/dev/urandom”的Tomcat系統屬性來縮小Tomcat的啓動時間。

如果你使用的是boot2docker,在你使用Docker命令或者使用構建工具構建(它運行在守護進程,在虛擬機上爲你工作)之前,你必須先啓動它。

構建Docker鏡像,你可以使用一些諸如Gradle或Maven的工具或者藉助社區(強烈感謝TransmodeSpotify提供這些工具)。

使用Maven構建Docker鏡像

在Maven的pom.xml中,你應該增加一個插件,如下。(參閱the plugin documentation獲取更多信息)。

pom.xml

<properties>
   <docker.image.prefix>springio</docker.image.prefix>
</properties>
<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.3.4</version>
            <configuration>
                <repository>${docker.image.prefix}/${project.artifactId}</repository>
            </configuration>
        </plugin>
    </plugins>
</build>

配置指定了兩個東西:

  • 鏡像名字,最終會在springio/gs-spring-boot-docker
  • 可選,鏡像的標籤,未指定默認爲latest,如果有需要的話,也可以指定artifact id

繼續下面的步驟之前(使用Docker CLI工具),輸入docker ps確保正常運行,如果有錯誤信息,大概因爲沒有設置其他什麼信息。如果使用的Mac,在.bash_profile(或者是類似env-setting配置文件)最後增加$(boot2docker shellinit 2> /dev/null)並刷新你的shell,確保更改生效。

你可以使用下面的命令來構建Docker的鏡像:

$ ./mvnw install dockerfile:build

你可以使用./mvnw dockerfile:push命令發佈鏡像到Docker鏡像中心去。

你不用着急發佈你剛剛製作的鏡像,如果你不是”springio”組織的成員push命令會失敗。改變構建的配置和命令行中的用戶名爲自己的而不是”springio”就可以正常工作。

你可以讓dockerfile:push自動運行在安裝或部署生命週期階段,通過將其添加到插件配置中。

pom.xml

<executions>
    <execution>
        <id>default</id>
        <phase>install</phase>
        <goals>
            <goal>build</goal>
            <goal>push</goal>
        </goals>
    </execution>
</executions>

使用Gradle構建Docker鏡像

如果你使用Gradle構建,添加如下插件:

build.gradle

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

group = 'springio'

...
apply plugin: 'docker'

task buildDocker(type: Docker, dependsOn: build) {
  applicationName = jar.baseName
  dockerfile = file('Dockerfile')
  doFirst {
    copy {
      from jar
      into "${stageDir}/target"
    }
  }
}

該配置指定了三個東西:
- 從jar文件屬性設置鏡像名字(或標籤),最終會出現在springio/gs-spring-boot-docker
- Dockerfile的位置
- 複製Maven構建目錄中的jar文件到相同的目錄,這樣我們就可以Maven或者Gradle構建鏡像而且使用同一個Dockerfile

你可以使用一下命令構建鏡像並且發佈到遠程倉庫:

$ ./gradlew build buildDocker

發佈之後

對你來說”Docker鏡像發佈”會失敗(除非你在Dockerhub中是”springio”組織的一員),但是如果你修改配置符合你自己的docker ID之後同樣會成功,你會有一個新的標籤,並且部署鏡像。

如果你沒有註冊docker,或者沒有發佈任何docker鏡像。但是你有一個本地的鏡像,你可以像這樣讓它運行起來:

$ docker run -p 8080:8080 -t springio/gs-spring-boot-docker
....
2015-03-31 13:25:48.035  INFO 1 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-03-31 13:25:48.037  INFO 1 --- [           main] hello.Application                        : Started Application in 5.613 seconds (JVM running for 7.293)

然後應用程序可以在http://localhost:8080/訪問(訪問可以看到”Hello Docker World”)。確保它是真的在工作,把”springio”前綴改成其他(比如${env.USER}並且重新構建運行)。

如果你使用mac的boot2docker,你通常在啓動時可以看到這樣的事情:

Docker client to the Docker daemon, please set:
    export DOCKER_CERT_PATH=/Users/gturnquist/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1
    export DOCKER_HOST=tcp://192.168.59.103:2376

查看應用程序,你必須訪問Docker主機而不是本地主機的ip(localhost),在這種情況下,http://192.168.59.103:8080/,對於VM來說就是開發的ip。

當它正在運行,你可以在容器列表中看到:

$ docker ps
CONTAINER ID        IMAGE                             COMMAND                CREATED             STATUS              PORTS                    NAMES
81c723d22865        springio/gs-spring-boot-docker:latest   "java -jar /app.jar"   34 seconds ago      Up 33 seconds       0.0.0.0:8080->8080/tcp   goofy_brown

你可以使用docker stop加上容器的id來關閉它。

$ docker stop 81c723d22865
81c723d22865

當然你喜歡你也可以刪除容器(它們都保存在/var/lib/docker文件目錄下)。

$ docker rm 81c723d22865

使用Spring Profiles

運行你新制作的鏡像使用Spring Profiles,和運行docker命令傳入一個環境變量一樣簡單。

$ docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker

$ docker run -e "SPRING_PROFILES_ACTIVE=dev" -p 8080:8080 -t springio/gs-spring-boot-docker

在Docker容器中調試應用程序

使用JPDA Transport可以調試應用程序,所以我們可以視容器爲一個服務器,啓用此功能通過java設置JAVA_OPTS變量和代理的端口映射到本地主機在一個容器中運行。對於Docker for Mac由於有限制,我們不能通過IP訪問容器因爲沒有black magic usage.

$ docker run -e "JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n" -p 8080:8080 -p 5005:5005 -t springio/gs-spring-boot-docker

總結

恭喜你!剛剛爲Spring Boot應用程序創建了Docker容器!Spring Boot應用程序在容器中運行默認端口8080映射到相同的宿主機端口使用”-p”參數。

另請參閱

以下教程也可能是有用的:

想寫一篇新的教程?或者爲舊教程出力?查看我們的貢獻參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章