知識庫 / Spring / Spring Boot RSS 訂閱

將 Spring Boot 應用容器化

Docker,Spring Boot
HongKong
4
02:46 PM · Dec 06 ,2025

1. 概述

在本教程中,我們將重點介紹如何將 Spring Boot 應用程序 打包成容器,以便在隔離的環境中運行,即 容器

我們將學習如何創建相互依賴且通過虛擬私有網絡鏈接在一起的容器組。我們還將看到如何使用單個命令協同管理它們。

讓我們從創建一個簡單的 Spring Boot 應用程序開始,然後將其運行在輕量級 Alpine Linux 鏡像中:Alpine Linux

2. 將 Spring Boot 獨立應用容器化

為了作為可容器化的應用示例,我們將創建一個簡單的 Spring Boot 應用,docker-message-server,它將暴露一個端點並返回一個靜態消息:

@RestController
public class DockerMessageController {
    @GetMapping("/messages")
    public String getMessage() {
        return "Hello from Docker!";
    }
}

使用正確配置的 Maven 文件,我們可以創建可執行的 JAR 文件:

$> mvn clean package

接下來,我們將啓動 Spring Boot 應用程序:

$> java -jar target/docker-message-server-1.0.0.jar

現在我們已經有一個可運行的 Spring Boot 應用程序,可以通過 localhost:8888/messages 訪問。

要將應用程序容器化,首先創建一個名為 Dockerfile 的文件,內容如下:

FROM openjdk:17-jdk-alpine
MAINTAINER baeldung.com
COPY target/docker-message-server-1.0.0.jar message-server-1.0.0.jar
ENTRYPOINT ["java","-jar","/message-server-1.0.0.jar"]

此文件包含以下信息:

  • 來源: 作為我們鏡像的基礎,我們將使用具有Java支持的Alpine Linux,該鏡像在上一節中創建。
  • 維護者: 鏡像的維護者。
  • 複製: 我們讓Docker將我們的 jar 文件複製到鏡像中。
  • ENTRYPOINT: 這將是容器啓動時執行的命令。 必須將其定義為JSON-Array,因為我們將使用ENTRYPOINTCMD 組合,以用於某些應用程序的參數。

要從我們的Dockerfile創建鏡像,我們必須像之前一樣運行‘docker build’

$> docker build --tag=message-server:latest .

最後,我們終於可以從我們的鏡像中運行容器:

$> docker run -p8887:8888 message-server:latest

這將啓動我們的應用程序,並在主機上通過 localhost:8887/messages 訪問它。 重要的是定義端口映射,將主機上的端口(8887)映射到 Docker 內部的端口(8888)。 這是我們在 Spring Boot 應用程序的屬性中定義的端口。

注意:在啓動容器的機器上,端口 8887 可能不可用。 如果發生這種情況,映射可能無法正常工作,我們需要選擇一個仍然可用的端口。

如果以非阻塞模式運行容器,可以使用以下命令檢查其詳細信息、停止和刪除它:

$> docker inspect message-server
$> docker stop message-server
$> docker rm message-server

2.1. 修改基礎鏡像

我們可以輕鬆地更改基礎鏡像,以便使用不同的 Java 版本。例如,如果我們想使用亞馬遜提供的 Corretto 分發版,只需更改 Dockerfile 即可:

FROM amazoncorretto:17-alpine-jdk
MAINTAINER baeldung.com
COPY target/docker-message-server-1.0.0.jar message-server-1.0.0.jar
ENTRYPOINT ["java","-jar","/message-server-1.0.0.jar"]

此外,我們還可以使用自定義的基礎鏡像。稍後在本教程中我們將詳細介紹如何進行操作。

3. 在複合環境中打包應用程序

<em >Docker</em> 命令和 <em >Dockerfiles</em> 尤其適合創建單個容器。但是,如果我們要在隔離應用程序的網絡上運行,容器管理就會變得混亂不堪。

為了解決這個問題,Docker 提供了名為 Docker Compose 的工具。該工具附帶自己的構建文件,格式為 YAML,更適合管理多個容器。例如,它能夠用一條命令啓動或停止複合服務,或者將多個服務的日誌輸出合併成一個 偽終端

3.1. 第二個 Spring Boot 應用

讓我們創建一個示例,其中兩個應用程序在不同的 Docker 容器中運行。它們將相互通信,並以“單一單元”的形式呈現給主機系統。作為簡單的示例,我們將創建一個第二個 Spring Boot 應用,名為 docker-product-server

@RestController
public class DockerProductController {
    @GetMapping("/products")
    public String getMessage() {
        return "A brand new product";
    }
}

我們以與 message-server 相同的方式構建和啓動該應用程序。

3.2. Docker Compose 文件

我們可以將兩個服務的配置合併到一個名為 docker-compose.yml 的文件中:

version: '2'
services:
    message-server:
        container_name: message-server
        build:
            context: docker-message-server
            dockerfile: Dockerfile
        image: message-server:latest
        ports:
            - 18888:8888
        networks:
            - spring-cloud-network
    product-server:
        container_name: product-server
        build:
            context: docker-product-server
            dockerfile: Dockerfile
        image: product-server:latest
        ports:
            - 19999:9999
        networks:
            - spring-cloud-network
networks:
    spring-cloud-network:
        driver: bridge
<ul>
  <li><strong>版本</strong>:指定應使用的格式版本。這是一個必填字段。我們這裏使用較新的版本,而 <em title="遺留格式">遺留格式</em> 為 ‘1’。</li>
  <li><strong>服務</strong>:此鍵中的每個對象定義了一個 <em title="服務">服務</em>,即容器。此部分是必填的。
    <ul>
      <li><strong>構建</strong>:如果提供,<em title="docker-compose">docker-compose</em> 可以從 <em title="Dockerfile">Dockerfile</em> 構建鏡像</li>
      <li><strong>上下文</strong>:如果提供,它指定構建目錄,其中 <em title="Dockerfile">Dockerfile</em> 被查找。</li>
      <li><strong>Dockerfile</strong>:如果提供,它為 <em title="Dockerfile">Dockerfile</em> 設置一個別名。</li>
    </ul></li>
  <li><strong>鏡像</strong>:告訴 <em title="Docker">Docker</em> 在使用構建功能時應將鏡像命名為什麼。否則,它將在庫或 <em title="remote-registry">遠程註冊表</em> 中搜索該鏡像。</li>
  <li><strong>網絡</strong>:在此部分,我們正在指定用於服務的 <em title="networks">網絡</em>。一個給定的 <em title="name-value">名稱-值</em> 必須列在 <em title="networks">網絡</em> 部分。</li>
</ul>
<p>在繼續之前,我們將檢查我們的構建文件是否存在語法錯誤:</p>
$> docker-compose config

然後我們可以構建我們的圖像,創建定義的容器,並使用一個命令啓動它:

$> docker-compose up --build

這將啓動 message-serverproduct-server

要停止容器,請從 Docker 中刪除它們,並從其中刪除連接的網絡。要執行此操作,可以使用相反的命令:

$> docker-compose down

要更詳細地瞭解 docker-compose,,您可以閲讀我們的文章《Docker Compose 介紹》。

3.3. 擴展服務

docker-compose 的一個優點是能夠擴展服務。例如,我們可以告訴 Docker 運行三個容器用於 message-server,以及兩個容器用於 product-server

但是,為了使這部分正常工作,我們需要從我們的 docker-compose.yml 中刪除 container_name,以便 Docker 可以選擇名稱,並更改 exposed port 配置 以避免衝突。

對於端口,我們可以告訴 Docker 將主機上的端口範圍映射到 Docker 內部的特定端口:

ports:
    - 18800-18888:8888

之後,我們能夠像這樣擴展我們的服務(請注意,我們正在使用一個修改過的 yml-文件):

$> docker-compose --file docker-compose-scale.yml up -d --build --scale message-server=1 --scale product-server=1

此命令將啓動一個 message-server 和一個 product-server

為了擴展我們的服務,可以使用以下命令:

$> docker-compose --file docker-compose-scale.yml up -d --build --scale message-server=3 --scale product-server=2

此命令將啓動兩個額外的消息服務器和一台額外的產品服務器。運行中的容器不會被停止。

4. 自定義基礎鏡像

我們之前使用的基礎鏡像(openjdk:17-jdk-alpine)包含了 Alpine 操作系統的一個發行版,其中已經預裝了 JDK 17。 此外,我們也可以構建自己的基礎鏡像(基於 Alpine 或任何其他操作系統)。

為此,我們可以使用一個 Dockerfile,其中 Alpine 用作基礎鏡像,並安裝我們選擇的 JDK:

FROM alpine:edge
MAINTAINER baeldung.com
RUN apk add --no-cache openjdk17
<ul>
 <li><strong>FROM</strong>: 關鍵字 <em>FROM</em> 告訴 <em>Docker</em> 使用指定鏡像及其標籤作為構建基礎。如果該鏡像不在本地庫中,則會執行對 <em><a href="https://hub.docker.com/explore/" target="_blank" rel="noopener noreferrer">DockerHub</a></em> 或任何其他配置的遠程註冊表的在線搜索。</li>
 <li><strong>MAINTAINER</strong>: <em>MAINTAINER</em> 通常是一個電子郵件地址,標識鏡像的作者。</li>
 <li><strong>RUN</strong>: 使用 <em>RUN</em> 命令,我們在目標系統內執行 shell 命令行。這裏我們使用 <em>Alpine Linux</em> 的包管理器 <em>apk</em> 安裝 <em>Java 8 OpenJDK</em>。</li>
</ul>
<p>要最終構建鏡像並將其存儲在本地庫中,我們需要運行:</p>
docker build --tag=alpine-java:base --rm=true .

注意:–tag選項將為圖像指定名稱,–rm=true選項將在構建成功後刪除中間圖像。該 shell 命令的最後一個字符是一個點,作為構建目錄參數。

現在我們可以使用創建的圖像,而不是openjdk:8-jdk-alpine

5. Spring Boot 2.3 中 Buildpacks 支持

Spring Boot 2.3 增加了對 Buildpacks 的支持。 簡單來説,我們無需再創建自己的 Dockerfile 並使用例如 docker build 這樣的工具進行構建,只需執行以下命令即可:

$ mvn spring-boot:build-image

同樣地,在Gradle中:

$ ./gradlew bootBuildImage

要使此操作生效,我們需要安裝並運行 Docker。

構建包的主要目的是創建一些知名雲服務(如 Heroku 或 Cloud Foundry)長期以來提供的相同部署體驗。我們只需運行 build-image 目標,然後平台本身負責構建和部署該 Artifact。

此外,它還可以幫助我們更有效地改變 Docker 鏡像的構建方式。而不是在不同的項目中對大量的 Dockerfile 應用相同的更改,我們只需更改或調整構建包鏡像構建器。

除了易用性和更好的整體開發者體驗外,它還可以更高效。例如,構建包方法將創建一個分層的 Docker 鏡像並使用 Jar 文件的展開版本。

讓我們看看在運行上述命令後會發生什麼。

當我們列出可用的 Docker 鏡像時:

docker image ls -a

我們看到剛剛創建的圖像的一行:

docker-message-server 1.0.0 b535b0cc0079

此處,鏡像名稱和版本與我們在 Maven 或 Gradle 配置文件中定義的名稱和版本匹配。哈希碼是鏡像的簡短版本。

要啓動我們的容器,我們只需運行:

docker run -it -p9099:8888 docker-message-server:1.0.0

與我們內置的鏡像類似,我們需要將端口映射出來,以便我們的 Spring Boot 應用程序能夠從 Docker 外部訪問。

6. 結論

在本文中,我們學習瞭如何構建自定義 Docker 鏡像,以 Docker 容器運行 Spring Boot Application,以及使用 docker-compose 創建容器。

有關構建文件的進一步閲讀,請參閲官方 構建文件參考docker-compose.yml 參考

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.