
本指南將引導您完成構建碼頭工人?用于運行 Spring 引導應用程序的映像。我們從一個基本開始,并進行一些調整。然后我們展示了幾個使用構建插件(用于 Maven 和 Gradle)而不是 .這是一個“入門”指南,因此范圍僅限于一些基本需求。如果要構建用于生產用途的容器映像,則需要考慮許多事項,并且不可能在簡短指南中涵蓋所有事項。??Dockerfile?
???docker?
?
還有一個關于 Docker 的主題指南,它涵蓋了我們在這里擁有的更廣泛的選擇,并且更詳細。
|
碼頭工人是一個具有“社交”方面的 Linux 容器管理工具包,允許用戶發布容器鏡像并使用其他人發布的容器鏡像。Docker 映像是運行容器化進程的方法。在本指南中,我們為一個簡單的 Spring 引導應用程序構建了一個。
如果您不使用 Linux 機器,則需要一臺虛擬化服務器。如果您安裝了VirtualBox,則Mac等其他工具可以為您無縫管理它。訪問??boot2docker?
?VirtualBox的下載網站,然后選擇適合您機器的版本。下載并安裝。不要擔心實際運行它。
您還需要碼頭工人,僅在 64 位計算機上運行。看https://docs.docker.com/installation/#installation了解有關為您的計算機設置 Docker 的詳細信息。在繼續操作之前,請驗證是否可以從 shell 運行命令。如果使用 ,則需要先運行它。??docker?
???boot2docker?
?
你可以使用這個預初始化項目,然后單擊生成以下載 ZIP 文件。此項目配置為適合本教程中的示例。
手動初始化項目:
導航到https://start.spring.io.此服務拉入應用程序所需的所有依賴項,并為您完成大部分設置。選擇 Gradle 或 Maven 以及您要使用的語言。本指南假定您選擇了 Java。單擊“依賴關系”,然后選擇“Spring Web”。單擊生成。下載生成的 ZIP 文件,該文件是配置了您選擇的 Web 應用程序的存檔。如果您的 IDE 集成了 Spring Initializr,則可以從 IDE 完成此過程。 |
您也可以從 Github 分叉項目,然后在 IDE 或其他編輯器中打開它。 |
現在,您可以創建一個簡單的應用程序:
??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@RestControllerpublic class Application { @RequestMapping("/") public String home() { return "Hello Docker World"; } public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
該類被標記為 a 和 a ,這意味著它已準備好供 Spring MVC 用于處理 Web 請求。 映射到發送響應的方法。該方法使用 Spring Boot 的方法啟動應用程序。??@SpringBootApplication?
???@RestController?
???@RequestMapping?
???/?
???home()?
???Hello World?
???main()?
???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
然后轉到??本地主機:8080??以查看您的“Hello Docker World”消息。
Docker有一個簡單的“Dockerfile”用于指定圖像“圖層”的文件格式。在 Spring 引導項目中創建以下 Dockerfile:
例 1.Dockerfile
FROM openjdk:8-jdk-alpineARG JAR_FILE=target/*.jarCOPY ${JAR_FILE} app.jarENTRYPOINT ["java","-jar","/app.jar"]
如果您使用 Gradle,則可以使用以下命令運行它:
docker build --build-arg JAR_FILE=build/libs/\*.jar -t springio/gs-spring-boot-docker .
如果使用 Maven,則可以使用以下命令運行它:
docker build -t springio/gs-spring-boot-docker .
此命令將生成映像并將其標記為 。??springio/gs-spring-boot-docker?
?
這個 Dockerfile 非常簡單,但它是運行 Spring Boot 應用程序所需要的一切,沒有任何多余的裝飾:只有 Java 和一個 JAR 文件。該構建將創建一個 spring 用戶和一個 spring 組來運行應用程序。然后(通過命令)將項目 JAR 文件復制到容器中,作為 ,在 中運行。使用 Dockerfile 的數組形式,以便沒有 shell 包裝 Java 進程。這??COPY?
???app.jar?
???ENTRYPOINT?
???ENTRYPOINT?
?關于 Docker 的主題指南將更詳細地討論此主題。
要減少雄貓啟動時間?,我們曾經添加一個指向熵源的系統屬性。這不再是必需的? |
使用用戶權限運行應用程序有助于降低某些風險(例如,請參閱:堆棧交換上的一個線程).因此,對 的一個重要改進是以非 root 用戶身份運行應用程序:??Dockerfile?
?
例 2.Dockerfile
FROM openjdk:8-jdk-alpineRUN addgroup -S spring && adduser -S spring -G springUSER spring:springARG JAR_FILE=target/*.jarCOPY ${JAR_FILE} app.jarENTRYPOINT ["java","-jar","/app.jar"]
生成并運行應用程序時,可以在應用程序啟動日志中看到用戶名:
docker build -t springio/gs-spring-boot-docker .docker run -p 8080:8080 springio/gs-spring-boot-docker
請注意第一個日志條目中的:??started by?
???INFO?
?
:: Spring Boot :: (v2.2.1.RELEASE)2020-04-23 07:29:41.729 INFO 1 --- [ main] hello.Application : Starting Application on b94c86e91cf9 with PID 1 (/app started by spring in /)...
此外,在 Spring Boot 胖 JAR 文件中,依賴項和應用程序資源之間存在清晰的分離,我們可以利用這一事實來提高性能。關鍵是在容器文件系統中創建層。這些層在構建時和運行時(在大多數運行時)都緩存,因此我們希望將最頻繁更改的資源(通常是應用程序本身中的類和靜態資源)分層在變化較慢的資源之后。因此,我們使用稍微不同的 Dockerfile 實現:
例 3.Dockerfile
FROM openjdk:8-jdk-alpineRUN addgroup -S spring && adduser -S spring -G springUSER spring:springARG DEPENDENCY=target/dependencyCOPY ${DEPENDENCY}/BOOT-INF/lib /app/libCOPY ${DEPENDENCY}/META-INF /app/META-INFCOPY ${DEPENDENCY}/BOOT-INF/classes /appENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]
這個 Dockerfile 有一個參數,指向我們解壓縮胖 JAR 的目錄。要將參數與 Gradle 一起使用,請運行以下命令:??DEPENDENCY?
???DEPENDENCY?
?
mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*.jar)
要將參數與 Maven 一起使用,請運行以下命令:??DEPENDENCY?
?
mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
如果我們做對了,它已經包含一個包含依賴 JAR 的目錄,以及一個包含應用程序類的目錄。請注意,我們使用應用程序自己的主類:。(這比使用胖 JAR 啟動器提供的間接尋址更快。??BOOT-INF/lib?
???BOOT-INF/classes?
???hello.Application?
?
分解 JAR 文件可能導致類路徑順序為運行時不同.一個行為良好且編寫良好的應用程序不應該關心這一點,但如果依賴項沒有得到仔細管理,您可能會看到行為變化。 |
如果使用 ,則需要先運行它,然后再使用 Docker 命令行或構建工具執行任何操作(它運行一個守護進程,在虛擬機中為您處理工作)。? |
在 Gradle 構建中,您需要在 Docker 命令行中添加顯式構建參數:
docker build --build-arg DEPENDENCY=build/dependency -t springio/gs-spring-boot-docker .
要在 Maven 中構建映像,可以使用更簡單的 Docker 命令行:
docker build -t springio/gs-spring-boot-docker .
當然,如果您只使用 Gradle,則可以更改默認值 使默認值 與解壓縮存檔的位置相匹配。? |
您可能希望使用構建插件,而不是使用 Docker 命令行進行構建。Spring Boot 支持使用自己的構建插件從 Maven 或 Gradle 構建容器。谷歌也有一個名為臂有Maven和Gradle插件。這種方法最有趣的地方可能是您不需要 .您可以使用與從 獲取的相同的標準容器格式來生成映像。此外,它可以在未安裝 docker 的環境中工作(在構建服務器中并不少見)。??Dockerfile?
???docker build?
?
默認情況下,默認構建包生成的映像不會以 root 用戶身份運行應用程序。查看配置指南格拉德爾?或馬文了解如何更改默認設置。 |
您可以在一個命令中使用 Gradle 構建標記的 docker 映像:
./gradlew bootBuildImage --imageName=springio/gs-spring-boot-docker
要快速入門,您可以運行 Spring 啟動映像生成器,甚至無需更改您的(請記住,如果仍然存在,則忽略):??pom.xml?
???Dockerfile?
?
./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=springio/gs-spring-boot-docker
要推送到 Docker 注冊表,您需要具有推送權限,默認情況下您沒有推送權限。將映像前綴更改為您自己的 Dockerhub ID,并確保在運行 Docker 之前進行身份驗證。??docker login?
?
示例中的 A 失敗(除非您是 Dockerhub 的“springio”組織的一部分)。但是,如果更改配置以匹配自己的 docker ID,則應該會成功。然后,您將擁有一個新的標記的已部署映像。??docker push?
?
您不必向 docker 注冊或發布任何內容即可運行本地構建的 docker 映像。如果你使用 Docker 構建(從命令行或從 Spring Boot),你仍然有一個本地標記的鏡像,你可以像這樣運行它:
$ docker run -p 8080:8080 -t springio/gs-spring-boot-dockerContainer memory limit unset. Configuring JVM for 1G container.Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=86381K -XX:ReservedCodeCacheSize=240M -Xss1M -Xmx450194K (Head Room: 0%, Loaded Class Count: 12837, Thread Count: 250, Total Memory: 1073741824)....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)
CF 內存計算器在運行時用于調整 JVM 的大小以適合容器。 |
然后,該應用程序可在??http://localhost:8080??(訪問它,它說,“你好碼頭工人世界”)。
將 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_HOST 中的 IP 地址而不是本地主機 — 在這種情況下,https://192.168.59.103:8080,VM 的面向公眾的 IP。 |
當它運行時,您可以在容器列表中看到,類似于以下示例:
$ docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES81c723d22865 springio/gs-spring-boot-docker:latest "java -Djava.secur..." 34 seconds ago Up 33 seconds 0.0.0.0:8080->8080/tcp goofy_brown
若要再次關閉它,可以使用上一個列表中的容器 ID 運行(你的 ID 會有所不同):??docker stop?
?
docker stop goofy_brown81c723d22865
如果您愿意,也可以在完成容器后刪除容器(它保留在文件系統中的某個位置):??/var/lib/docker?
?
docker rm goofy_brown
使用 Spring 配置文件運行新創建的 Docker 映像就像將環境變量傳遞給 Docker run 命令(對于配置文件)一樣簡單:??prod?
?
docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker
您可以對配置文件執行相同的操作:??dev?
?
docker run -e "SPRING_PROFILES_ACTIVE=dev" -p 8080:8080 -t springio/gs-spring-boot-docker
若要調試應用程序,可以使用JPDA 運輸.我們將容器視為遠程服務器。要啟用此功能,請在變量中傳遞 Java 代理程序設置,并在容器運行期間將代理程序的端口映射到本地主機。跟JAVA_OPTS適用于 Mac 的 Docker,有一個限制,因為我們無法通過 IP 訪問容器,沒有黑魔法用法.
docker run -e "JAVA_TOOL_OPTIONS=-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 引導應用程序在容器內的端口 8080 上運行,我們通過命令行將其映射到主機上的同一端口。??-p?
?