帶Docker的Spring Boot
本指南將指導您構建運行Spring Boot應用程序的Docker鏡像的過程。
你要建造什麼
Docker是一個具有“社交”方面的Linux容器管理工具包,允許用戶發佈容器圖像並使用其他人發佈的容器圖像。Docker鏡像是運行容器化過程的配方,在本指南中,我們將爲簡單的Spring啓動應用程序構建一個。
你需要什麼
-
大約15分鐘
-
最喜歡的文本編輯器或IDE
-
JDK 1.8或更高版本
-
您還可以將代碼直接導入IDE:
如果您不使用Linux計算機,則需要虛擬化服務器。通過安裝VirtualBox,Mac的boot2docker等其他工具可以爲您無縫管理。訪問VirtualBox的下載站點,選擇適合您機器的版本。下載並安裝。不要擔心實際運行它。
您還需要Docker,它只能在64位計算機上運行。有關爲計算機設置Docker的詳細信息,請參閱https://docs.docker.com/installation/#installation。在繼續之前,請驗證您是否可以docker
從shell 運行命令。如果你正在使用boot2docker你需要運行第一。
如何完成本指南
與大多數Spring 入門指南一樣,您可以從頭開始並完成每個步驟,或者您可以繞過您已熟悉的基本設置步驟。無論哪種方式,您最終都會使用工作代碼。
要從頭開始,請繼續使用Gradle構建。
要跳過基礎知識,請執行以下操作:
-
下載並解壓縮本指南的源存儲庫,或使用Git克隆它:
git clone https://github.com/spring-guides/gs-spring-boot-docker.git
-
進入
gs-spring-boot-docker/initial
完成後,您可以根據代碼檢查結果gs-spring-boot-docker/complete
。
設置一個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);
}
}
該類被標記爲a @SpringBootApplication
和as @RestController
,這意味着它可以由Spring MVC用於處理Web請求。@RequestMapping
映射/
到home()
只發送“Hello World”響應的方法。該main()
方法使用Spring Boot的SpringApplication.run()
方法來啓動應用程序。
現在我們可以在沒有Docker容器的情況下運行應用程序(即在主機操作系統中)。
如果您使用的是Gradle,請執行:
./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文件格式,用於指定圖像的“圖層”。那麼讓我們繼續在Spring Boot項目中創建一個Dockerfile:
Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
這個Dockerfile非常簡單,但是你需要運行一個沒有多餘裝飾的Spring Boot應用程序:只需要Java和一個JAR文件。項目JAR文件ADDed
作爲“app.jar”到容器,然後在ENTRYPOINT
。
我們添加了一個VOLUME 指向“/ tmp”的內容,因爲這是Spring Boot應用程序默認爲Tomcat創建工作目錄的地方。效果是在主機“/ var / lib / docker”下創建一個臨時文件,並將其鏈接到“/ tmp”下的容器。對於我們在此處編寫的簡單應用程序,此步驟是可選的,但如果需要在文件系統中實際編寫,則對於其他Spring Boot應用程序可能是必需的。 |
爲了減少Tomcat的啓動時間,我們添加了一個指向“/ dev / urandom”的系統屬性作爲熵源。如果您使用Tomcat(或任何其他Web服務器)的“標準”版本,則對於更新版本的Spring Boot,這不是必需的。 |
爲了利用Spring Boot胖jar文件中依賴項和應用程序資源之間的清晰分離,我們將使用稍微不同的Dockerfile實現:
Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=target/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]
這個Dockerfile有一個DEPENDENCY
參數指向我們解壓縮胖jar的目錄。如果我們做對了,它已經包含一個BOOT-INF/lib
帶有依賴項jars的BOOT-INF/classes
目錄,以及一個包含應用程序類的目錄。請注意,我們正在使用應用程序自己的主類hello.Application
(這比使用胖jar啓動器提供的間接更快)。
如果你正在使用boot2docker你需要運行它首先,你與泊塢窗命令行或生成工具(它運行的守護進程來處理你在虛擬機的工作)做任何事情之前。 |
要構建圖像,您可以從社區使用Maven或Gradle的一些工具(非常感謝Palantir和Spotify提供這些工具)。
使用Maven構建Docker鏡像
在Maven中pom.xml
你應該添加一個這樣的新插件(有關更多選項,請參閱插件文檔)::
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.6</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
</configuration>
</plugin>
</plugins>
</build>
配置指定了1個必需的東西:具有圖像名稱的存儲庫,最終將在此處作爲springio/gs-spring-boot-docker
。
其他一些屬性是可選的:
-
胖jar將要解壓縮的目錄的名稱,將Maven配置公開爲docker的構建參數。可以使用
<buildArgs/>
插件配置指定它。 -
圖像標記,如果未指定則最終爲“最新”。它可以用
<tag/>
元素設置,
在繼續執行以下步驟(使用Docker的CLI工具)之前,請確保通過鍵入正確運行Dockerdocker ps 。如果收到錯誤消息,可能無法正確設置某些內容。用Mac?添加$(boot2docker shellinit 2> /dev/null) 到您的.bash_profile (或類似的環境設置配置文件)的底部並刷新shell以確保配置了正確的環境變量。 |
爲確保在創建docker鏡像之前解壓縮jar,我們爲依賴項插件添加一些配置:
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
您可以使用命令行構建標記的docker鏡像,如下所示:
$ ./mvnw install dockerfile:build
你可以將圖像推送到dockerhub ./mvnw dockerfile:push
。
您不必將新創建的Docker鏡像推送到實際運行它。此外,如果您不是Dockerhub上“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('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.13.0')
}
}
group = 'springio'
...
apply plugin: 'com.palantir.docker'
task unpack(type: Copy) {
dependsOn bootJar
from(zipTree(tasks.bootJar.outputs.files.singleFile))
into("build/dependency")
}
docker {
name "${project.group}/${bootJar.baseName}"
copySpec.from(tasks.unpack.outputs).into("dependency")
buildArgs(['DEPENDENCY': "dependency"])
}
配置指定了4件事:
-
解壓胖jar文件的任務
-
圖像名稱(或標記)是從jar文件屬性設置的,最終將在此處作爲
springio/gs-spring-boot-docker
-
解壓縮的jar文件的位置,我們可以在其中進行硬編碼
Dockerfile
-
docker指向jar文件的構建參數
您可以構建標記的docker鏡像,然後使用Gradle將其推送到遠程存儲庫:
$ ./gradlew build docker
推後
“docker push”將失敗(除非您是Dockerhub中“springio”組織的一部分),但是如果您更改配置以匹配您自己的docker ID,那麼它應該會成功,並且您將有一個新的標記,部署圖片。
您不必註冊docker或發佈任何東西來運行docker鏡像。您仍然擁有本地標記的圖像,您可以像這樣運行它:
|
然後可以在http:// localhost:8080上訪問該應用程序(訪問它並顯示“Hello Docker World”)。要確保整個過程真正起作用,請將前綴從“springio”更改爲其他內容(例如${env.USER}
),然後再從構建到docker run再次查看。
將Mac與boot2docker一起使用時,通常會在啓動時看到類似的內容:
要查看應用程序,您必須訪問DOCKER_HOST中的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 -Djava.secur..." 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配置文件
使用Spring配置文件運行剛剛創建的Docker鏡像就像將環境變量傳遞給Docker run命令一樣簡單
$ 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_OPTS變量中傳遞Java代理設置,並在容器運行期間將代理程序的端口映射到localhost。使用Docker for Mac存在限制,因爲我們無法通過IP訪問容器而不使用黑魔法。
$ 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-dockerspan>
摘要
恭喜!您剛剛爲Spring Boot應用程序創建了一個Docker容器!默認情況下,Spring Boot應用程序在容器內的端口8080上運行,我們使用命令行上的“-p”將其映射到主機上的同一端口。
也可以看看
以下指南也可能有所幫助:
想要撰寫新指南或爲現有指南做出貢獻?查看我們的貢獻指南。
所有指南均附有代碼的ASLv2許可證,以及Attribution,NoDerivatives創作公共許可證。 |