日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

docker build -t_在Docker环境构建、打包和运行Spring Boot应用

發布時間:2025/3/12 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 docker build -t_在Docker环境构建、打包和运行Spring Boot应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為何考慮采用Docker?

Docker是提供用戶構建鏡像的一種容器化技術,所構建的鏡像包含了主要的應用程序和運行應用所需的所有依賴項。該鏡像可在任何虛擬機或物理機器上的Docker容器上運行。它的強大之處在于允許用戶在開發、測試、預生產和生產中運行同樣的鏡像,而不必擔心在每個環境中依賴項的安裝或配置。采用Docker構建和運行應用

以Java程序員的視角看,Docker的典型應用場景是在容器內運行應用。這固然不錯,但如果Docker能提供應用的構建是不是更好?本文中,我將演示如何在容器內用Docker來編排、構建和運行Spring Boot應用。請先按如下步驟創建一個Docker鏡像:
  • 從源主機復制應用程序源代碼到鏡像的臨時構建目錄

  • 采用Maven完成應用的編譯和打包,生成可執行的JAR文件

  • 采用JRE運行JAR文件

鏡像大小的提示

關注所構建鏡像文件的大小非常重要。較小的鏡像文件具有更快的構建速度、下載速度和更低的存儲成本優勢。所以要盡可能地讓鏡像只包括所需的幾項組件即可。采用較小的基本鏡像同樣的道理,選用只包含必須功能的基礎鏡像文件也是最佳的選擇。本文后續采用Alpine鏡像也是基于同樣考慮,Alpine是只有5MB的超細Linux發行版。非常適合構建精細的鏡像。同時Alpine提供一個包管理器,讓用戶可以安裝任何需要的包。但由于Alpine的初始包非常小,所以安裝大量包的過程會有些麻煩。如果有看DockerHub的話,就會發現很多流行的鏡像都提供了Alpine版,可以直接使用。后續我們也將用到Alpine版本的Maven和Open JDK JRE鏡像。拋棄不需要的內容在稍后過程中所定義編譯、打包并運行的Spring Boot應用的鏡像。就是可部署運行的最終Docker鏡像,因此它只需要包含應用本身和運行時依賴項,能夠滿足在單個容器中構建和運行就可以了。也就是說它可以純粹就是可執行的JAR包和運行所需的Java JRE文件,而無需包含Maven(包括本地Maven庫)或目標目錄的全部內容。那么,用戶所要做的就是構建應用,然后從最終鏡像中剔除不需要的內容。這個正是多階段構建的作用所在。它允許用戶將Docker構建分解為不同的步驟,并在步驟之間復制特定的目標項,拋棄非必須的內容,從而實現拋棄構建工具本身和其他對應用沒有關聯的內容。測試案例執行步驟

項目構建非常簡單,舉個例子,我用一個類創建一個標準的Spring Boot應用,并在項目的根目錄中添加了一個Dockerfile。(用戶可在GitHub[1]上獲取這個實驗的完整源代碼,同步實驗。)

主類的代碼顯示如下,且沒有添加任何其他內容。接下來我將采用默認的執行器健康狀況端點來測試這個應用。

package com.blog.samples.docker;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class Application {

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

}

定義Docker鏡像

如下內容是Dockerfile中定義的鏡像文件,盡管內容不多,但包含了很多步的工作。我將在下面詳細解釋每一行。

FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD

MAINTAINER Brian Hannaway

COPY pom.xml /build/

COPY src /build/src/

WORKDIR /build/

RUN mvn package

FROM openjdk:8-jre-alpine

WORKDIR /app

COPY --from=MAVEN_BUILD /build/target/docker-boot-intro-0.1.0.jar /app/

ENTRYPOINT ["java", "-jar", "docker-boot-intro-0.1.0.jar"]

代碼備注:FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD告知Docker采用Maven編譯器。maven:3.5.2-jdk-8-alpine構建第一步采用的基礎鏡像,Docker將首先在本地查找鏡像,本地不存在后,將從DockerHub拉取。Maven會在最后階段被剔除掉(后續COPY命令介紹)考慮下載快速和鏡像大小控制的原因,選擇Alpine版的Maven鏡像。MAINTAINERBrianHannaway非必選項,但是為映像作者提供一個接觸點可提高可維護性。(本實驗應用驗證的點)COPY pom.xml/build/在鏡像中創建一個build目錄, 并拷入pom.xml文件。COPY src/build/src/拷入src目錄到鏡像中build目錄。WORKDIR/build/設置build為工作目錄。后續任何命令都在此目錄中運行。RUN mvnpackage執行mvn包來運行編譯和打包應用,生成成可執行的JAR文件。在第一次構建鏡像時,Maven將從公共Maven庫拉取所有需要的依賴項,并將它們緩存在鏡像的本地。后續的構建將使用這個緩存版的鏡像層,這意味著依賴項將在本地引用,而不必再次從外部拉取。至此,已經完成了鏡像定義,只需等其構建成一個可執行的JAR文件。這是多階段構建的第一部分。下一階段將獲取JAR并運行它。FROM openjdk:8-jre-alpine告知Docker多階段構建的下一步采用openjdk:8-jre-alpine的基礎鏡像。再次使用Java 8 JRE的Alpine版本,這一步的選擇其實比前面的Maven版本選擇更為重要,因為存在于最終版的鏡像只是openjdk:8-jre-alpine,因此如果要盡可能控制最終鏡像大小的話,選擇輕量級JRE鏡像就非常重要。WORKDIR/app告知Docker在鏡像內創建另一個/app工作目錄,后續任何命令都在此目錄中運行。COPY--from=MAVEN_BUILD/build/target/docker-boot-intro-0.1.0.jar/app/告知Docker從MAVEN_BUILD階段的/build/target目錄復制ocker-boot-intro-0.1.0.jar到/app目錄。如前文所述,多階段構建的優勢就是允許用戶將特定的內容從一個構建階段復制到另一個構建階段,并丟棄其他所有的內容。如果需要保留從MAVENBUILD階段開始的所有內容,那最終鏡像會包含Maven(包括Maven本地庫)工具,以及目標目錄中生成的所有類文件。通過從MAVENBUILD階段選擇必須要的內容,那最終得到的鏡像會小很多。ENTRYPOINT["java","-jar","app.jar"]告知Docker在容器運行本鏡像時,運行哪些命令。本部分用冒號進行多命令的隔離。本案例中,需要把執行JAR文件復制到/app目錄運行。構建鏡像

完成Docker鏡像定義后,就可以著手構建。打開包含Dockerfile(根目錄)的目錄。運行以下命令構建鏡像:

docker image build -t docker-boot-intro

-t參數為指定名稱和可選標簽。如果不指定標簽,Docker會自動標記為最latest。

$ docker image build -t docker-boot-intro .

Sending build context to Docker daemon 26.56MB

Step 1/10 : FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD

---> 293423a981a7

Step 2/10 : MAINTAINER Brian Hannaway

---> Using cache

---> db354a426bfd

Step 3/10 : COPY pom.xml /build/

---> Using cache

---> 256340699bc3

Step 4/10 : COPY src /build/src/

---> Using cache

---> 65eb0f98bb79

Step 5/10 : WORKDIR /build/

---> Using cache

---> b16b294b6b74

Step 6/10 : RUN mvn package

---> Using cache

---> c48659e0197e

Step 7/10 : FROM openjdk:8-jre-alpine

---> f7a292bbb70c

Step 8/10 : WORKDIR /app

---> Using cache

---> 1723d5b9c22f

Step 9/10 : COPY --from=MAVEN_BUILD /build/target/docker-boot-intro-0.1.0.jar /app/

---> Using cache

---> d0e2f8fbe5c9

Step 10/10 : ENTRYPOINT ["java", "-jar", "docker-boot-intro-0.1.0.jar"]

---> Using cache

---> f265acb14147

Successfully built f265acb14147

Successfully tagged docker-boot-intro:latest

SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

Brians Computer@DESKTOP-077OUJ8 MINGW64 /c/dev/docker-boot-intro (master)

運行構建時,Docker將逐條執行Docker文件中的每個命令。為每個步驟創建一個帶有唯一ID的層。例如,步驟1創建的層的ID為293423a981a7。第一次構建圖像時,Docker將從DockerHub獲取它需要的任何外部圖像,然后在此之上開始構建新的層。這會使得第一次構建速度非常慢。在構建過程中,Docker在嘗試構建層之前會檢查緩存,看看是否已經有所構建層的緩存版本。如果該層的緩存版本可用,Docker將直接使用它而不是從頭開始構建。這意味著一旦構建了一個鏡像層,后續的構建就是重用,速度會快很多。你可以在上面的構建輸出中通過Docker緩存輸出的hash值看到使用了緩存層。以上面第6步所發生的為例:作為RUN mvn包命令的一部分,Docker將從公共Maven庫獲取所有POM依賴項,構建成一個可執行JAR,并將所有這些內容存儲在ID為c48659e0197e的層中。下一次構建這個鏡像時,Maven依賴項和應用程序JAR將從緩存層中取出,而不必再次下載和構建。鏡像大小

運行docker image ls命令將羅列出所有的本地鏡像。可發現docker-boot-intro鏡像大小為105 MB。

Brians Computer@DESKTOP-077OUJ8 MINGW64 /c/dev/docker-boot-intro (master)

$ docker image ls

REPOSITORY TAG IMAGE ID CREATED SIZE

docker-boot-intro latest 823730301d60 15 minutes ago 105MB

853d42b823c3 15 minutes ago 136MB

39ac5e9e9562 19 minutes ago 105MB

dfda2356bd36 19 minutes ago 136MB

Brians Computer@DESKTOP-077OUJ8 MINGW64 /c/dev/docker-boot-intro (master)

我在前文中提到過盡可能保持鏡像大小的最佳實踐,接下來讓我們細探一下docker-boot-intro鏡像的105MB由什么組成的。運行如下命令:

docker image history boot-docker-intro

將看到鏡像中各個層的內容情況。

Brians Computer@DESKTOP-077OUJ8 MINGW64 /c/dev/docker-boot-intro/target (master)

$ docker image history docker-boot-intro

IMAGE CREATED CREATED BY SIZE COMMENT

823730301d60 19 minutes ago /bin/sh -c #(nop) ENTRYPOINT ["java" "-jar"... 0B

7e43d899f02f 19 minutes ago /bin/sh -c #(nop) COPY file:05f3666306f8c7af... 20.1MB

1723d5b9c22f 6 days ago /bin/sh -c #(nop) WORKDIR /app 0B

f7a292bbb70c 4 months ago /bin/sh -c set -x && apk add --no-cache o... 79.4MB

4 months ago /bin/sh -c #(nop) ENV JAVA_ALPINE_VERSION=8... 0B

4 months ago /bin/sh -c #(nop) ENV JAVA_VERSION=8u212 0B

4 months ago /bin/sh -c #(nop) ENV PATH=/usr/local/sbin:... 0B

4 months ago /bin/sh -c #(nop) ENV JAVA_HOME=/usr/lib/jv... 0B

4 months ago /bin/sh -c { echo '#!/bin/sh'; echo 'set... 87B

4 months ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B

4 months ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B

4 months ago /bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6a... 5.53MB

Brians Computer@DESKTOP-077OUJ8 MINGW64 /c/dev/docker-boot-intro/target (master)

如上所顯示5.53 MB的Alpine基礎鏡像處于第一層。在之上的幾層配置了一系列的環境變量,然后是大小為79.4 MB的JRE文件。最后的3層是我們在Dockerfile中定義的層,并包含了20.1 MB的應用JAR。可以發現這個鏡像只包括了運行應用所必須的組件,是一個非常不錯的輕量級鏡像。運行容器

鏡像構建好后,可以使用以下命令運行一個容器:

docker container run -p 8080:8080 docker-boot-intro

run命令包括一個可選的-p參數,作用是允許用戶將容器應用的端口映射到主機的端口。熟悉Spring Boot的人都知道,應用程序的默認啟動端口就是8080。運行一個容器時,Docker將運行可執行JAR文件來啟動應用,使用容器的8080端口。但如果要訪問容器中的應用,需要通過主機的端口訪問,通過端口映射去到容器端口。-p 8080:8080參數就是將容器端口8080映射到主機端口8080。如果沒有異常的話,應該可以看到應用程序在端口8080成功啟動的信息。

Brians Computer@DESKTOP-077OUJ8 MINGW64 /c/dev/docker-boot-intro/target (master)

$ docker container run -p 8080:8080 docker-boot-intro

. ____ _ __ _ _

/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \

( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \

\\/ ___)| |_)| | | | | || (_| | ) ) ) )

' |____| .__|_| |_|_| |_\__, | / / / /

=========|_|==============|___/=/_/_/_/

:: Spring Boot :: (v2.1.7.RELEASE)

5436 [main] INFO com.blog.samples.docker.Application - Starting Application v0.1.0 on 934a1d731576 with PID 1 (/app/docker-boot-intro-0.1.0.jar started by root in /app)

5466 [main] INFO com.blog.samples.docker.Application - No active profile set, falling back to default profiles: default

16585 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)

16742 [main] INFO o.a.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]

16886 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat]

16892 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.22]

17622 [main] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext

17628 [main] INFO o.s.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 11614 ms

21399 [main] INFO o.s.s.c.ThreadPoolTaskExecutor - Initializing ExecutorService 'applicationTaskExecutor'

23347 [main] INFO o.s.b.a.e.web.EndpointLinksResolver - Exposing 2 endpoint(s) beneath base path '/actuator'

23695 [main] INFO o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]

23791 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''

23801 [main] INFO com.blog.samples.docker.Application - Started Application in 21.831 seconds (JVM running for 25.901)

應用測試

如果看到類似于上面顯示的信息輸出,那表示容器已經順利啟動。接下來就可以測試應用。如果你在Windows或Mac上運行Docker,需要使用的工具是一個Linux虛擬機Docker Toolbox。需要通過運行docker-machine ip命令可以獲得Linux VM的IP地址。本案例中的Linux VM IP是192.168.99.100。

Brians Computer@DESKTOP-077OUJ8 MINGW64 /c/dev/docker-boot-intro (master)

$ docker-machine ip

192.168.99.100

獲得IP后,可以使用cURL命令cURL 192.168.99.100:8080/actuator/health來調用應用的健康檢查點來測試應用情況。如果應用程序啟動并運行正常,即可獲得HTTP 200的響應,響應內容為{“status”:“up”}。

Brians Computer@DESKTOP-077OUJ8 MINGW64 /c/dev/docker-boot-intro (master)

$ curl 192.168.99.100:8080/actuator/health

% Total % Received % Xferd Average Speed Time Time Time Current

Dload Upload Total Spent Left Speed

100 15 0 15 0 0 937 0 --:--:-- --:--:-- --:--:-- 937{"status":"UP"}

本方法的局限性

我在前文提到過,可以重用Docker緩存層以減少構建時間。雖然這是事實,但是在構建Java應用時需要考慮存在的例外。每當對Java源代碼或POM文件進行更改后,Docker將會發現變更差異,從而忽略緩存的副本層,重新構建所需的層。這是正常的,但問題是這個變化會導致緩存中的Maven依賴項丟失。因此,當使用mvn包命令重新構建這個層時,所有Maven依賴項將再次從遠程庫中拉取一次,導致顯著減慢了構建的速度,成為開發過程中真正的痛點。而且這個問題在構建沒有Docker的Java應用程序時完全不存在,僅僅發生在使用Docker構建應用層時發生。解決方案是什么?

目前解決這個問題的方法是使用主機上的本地Maven存儲庫作為Maven依賴項的源。通過卷告訴Docker去訪問主機本地的Maven庫,而非從公共庫中拉取依賴項。這種方法可以解決這個問題。但也是有利有弊。從好的方面看,你使用的是主機緩存的Maven依賴項,可以在更改源代碼后,快速重新構建,節省了構建時間。但不利的方面是Docker鏡像的管理因此而失去了一些自主性。使用Docker的主要初衷之一就是不必擔心在其運行的環境中的軟件配置。理想情況下,Docker鏡像應該是自我構建且擁有構建和運行所需的一切元素,而不必存在主機依賴。而這個方法恰好違背了這個初衷,讓Docker構建失去了部分自主性。在下一篇文章中,我們將介紹Docker卷,并展示如何使用它們訪問主機上的Maven庫。結束語

在本文中,我們定義了一個Docker鏡像來構建和運行一個Spring Boot應用程序。我們討論了讓鏡像保持盡可能小的重要性,可以通過使用超級小的Alpine基礎鏡像和在多階段構建過程中進行內容剔除的方式來實現。我們還討論了使用Docker構建Java應用程序的局限性和可能的解決方案。用戶可以從GitHub[1]獲取文章中的測試完整源代碼。相關鏈接:
  • https://github.com/briansjavablog/build-and-run-spring-boot-with-docker

  • 原文鏈接:https://dzone.com/articles/build-package-and-run-spring-boot-apps-with-docker基于Kubernetes的DevOps實戰培訓

    基于Kubernetes的DevOps實戰培訓將于2019年12月27日在上海開課,3天時間帶你系統掌握Kubernetes,學習效果不好可以繼續學習。本次培訓包括:容器特性、鏡像、網絡;Kubernetes架構、核心組件、基本功能;Kubernetes設計理念、架構設計、基本功能、常用對象、設計原則;Kubernetes的數據庫、運行時、網絡、插件已經落地經驗;微服務架構、組件、監控方案等,點擊下方圖片或者閱讀原文鏈接查看詳情。

    總結

    以上是生活随笔為你收集整理的docker build -t_在Docker环境构建、打包和运行Spring Boot应用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。