容器可在開發、測試和生產階段,為您的 Java 應用程式提供一致的可攜式環境。 本文介紹 Java 應用程式的容器化概念,並引導您建立、偵錯、優化和將容器化 Java 應用程式部署至 Azure Container Apps。
在本文中,您將瞭解 Java 開發人員的基本容器化概念,以及下列技能:
- 設定容器化 Java 應用程式的開發環境。
- 建立針對 Java 工作負載最佳化的 Dockerfile。
- 使用容器設定本機開發工作流程。
- 偵錯容器化 Java 應用程式。
- 優化生產環境的Java容器。
- 將您的容器化 Java 應用程式部署至 Azure Container Apps。
藉由容器化 Java 應用程式,您就能取得一致的環境、簡化的部署、有效率的資源使用率,以及改善的延展性。
適用於 Java 應用程式的容器
容器會使用其相依性封裝應用程式,以確保環境之間的一致性。 對於 Java 開發人員來說,這表示將應用程式、其相依性、Java 運行時間環境/Java 開發工具包 (JRE/JDK) 和組態檔結合成單一可攜式單位。
容器化在虛擬化上具有關鍵優勢,因此適合用於雲端開發。 相較於虛擬機,容器會在伺服器的主機OS核心上執行。 這對已在 Java 虛擬機 (JVM) 中執行的 Java 應用程式很有説明。 容器化 Java 應用程式會增加最少的額外負荷,並提供顯著的部署優點。
容器生態系統包含下列重要元件:
- 影像 - 藍圖。
- 容器 - 執行中的實例。
- 登錄 - 儲存映像的位置。
- 協調流程工具 - 可大規模管理容器的系統。
Docker 是最受歡迎的容器化平臺,而且透過 Azure Container Apps 在 Azure 生態系統中受到很好的支援。
設定開發環境
本節將引導您安裝必要的工具和設定開發環境,以建置、執行和偵錯容器化 Java 應用程式。
安裝所需工具
若要容器化 Java 應用程式,您需要在開發電腦上安裝下列工具:
- Docker Desktop。 提供適用於 Windows 或 macOS 的 Docker 引擎、CLI 和 Docker Compose。
- Visual Studio Code。 以免費程式代碼編輯器的形式提供。
- 下列 Visual Studio Code 延伸模組:
- 用於管理容器的 Docker 擴充功能。
- 適用於 Java 開發的 Java 延伸模組套件 。
- 用於在容器內開發的開發容器。
使用下列命令來確認您的安裝:
docker --version
docker compose version
設定 Visual Studio Code 以進行容器開發
若要在容器中進行 Java 開發,請安裝 Java Extension Pack 並設定 JDK,以完成 Visual Studio Code 設定。 開發容器延伸模組可讓您開啟容器內的任何資料夾,並使用該容器內Visual Studio Code的完整功能集。
若要讓 Visual Studio Code 自動建置並連線到開發容器,請在專案中建立 .devcontainer/devcontainer.json 檔案。
例如,下列範例組態會定義Java組建:
{
"name": "Java Development",
"image": "mcr.microsoft.com/devcontainers/java:21",
"customizations": {
"vscode": {
"extensions": [
"vscjava.vscode-java-pack",
"ms-azuretools.vscode-docker"
]
}
},
"forwardPorts": [8080, 5005],
"remoteUser": "vscode"
}
此組態會使用 Microsoft 的 Java 開發容器映像、新增基本擴充功能,以及轉送應用程式埠 8080和偵錯埠 5005。
建立 Dockerfile
Dockerfile 包含建置 Docker 映像的指示。 針對 Java 應用程式, Dockerfile 通常包含下列元件:
- 含有 JDK 或 JRE 的基底映像。
- 複製應用程式檔的指示。
- 設定環境變數的命令。
- 進入點的設定。
選取基底映像
選擇正確的基底映像非常重要。 請考慮下列選項:
| 說明 | 名稱 | 備註 |
|---|---|---|
| Microsoft Java 開發映像 | mcr.microsoft.com/java/jdk:21-zulu-ubuntu |
完整 JDK 並針對 Azure 優化 |
| Microsoft Java 產品映像檔 | mcr.microsoft.com/java/jre:21-zulu-ubuntu |
僅執行階段,且已針對 Azure 最佳化 |
| 官方 OpenJDK 開發映像 | openjdk:21-jdk |
完整的 JDK |
| 官方 OpenJDK 生產映像 | openjdk:21-jre |
僅執行階段 |
針對開發環境,請使用完整的 JDK 映像。 針對生產環境,請使用 JRE 或無發行版映像,將應用程式的大小和攻擊面降到最低。
Microsoft Java 映像具備 Azure 專屬最佳化,並會定期更新安全性修補程式,因此非常適合以 Azure 容器應用程式為目標的應用程式。
基本 Dockerfile 範例
下列範例顯示 Java 應用程式的簡單 Dockerfile:
FROM mcr.microsoft.com/java/jdk:21-zulu-ubuntu
WORKDIR /app
COPY target/myapp.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
針對 Spring Boot 應用程式,您可以使用下列基底來設定 Dockerfile :
FROM mcr.microsoft.com/java/jdk:21-zulu-ubuntu
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-Dspring.profiles.active=docker", "-jar", "app.jar"]
針對生產環境部署,請使用下列範例所示的 JRE 映像來減少大小,並將應用程式的攻擊面降到最低:
FROM mcr.microsoft.com/java/jre:21-zulu-ubuntu
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENV JAVA_OPTS="-Dserver.port=8080"
ENTRYPOINT ["java", ${JAVA_OPTS}, "-jar", "app.jar"]
使用容器進行本地化開發
容器可在各種內容中執行。 在本節中,您將瞭解在地開發流程,以便與容器一起使用。
針對多容器應用程式使用 Docker Compose
大部分的 Java 應用程式都會與資料庫、快取或其他服務互動。 Docker Compose 可協助您使用簡單的 YAML 組態檔來定義及協調多容器應用程式。
什麼是 Docker Compose?
Docker Compose 是可讓您執行下列工作的工具:
- 在單一檔案中定義多容器應用程式。
- 管理應用程式生命週期,包括啟動、停止和重建。
- 維護隔離的環境。
- 建立服務通訊的網路。
- 使用磁碟區保存資料。
範例:具有資料庫的 Java 應用程式
下列 compose.yml 檔案會使用 PostgreSQL 資料庫來設定 Java 應用程式:
version: '3.8'
services:
app:
build: . # Build from Dockerfile in current directory
ports:
- "8080:8080" # Map HTTP port
- "5005:5005" # Map debug port
environment:
- SPRING_PROFILES_ACTIVE=dev
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/myapp
volumes:
- ./target:/app/target # Mount target directory for hot reloads
depends_on:
- db # Ensure database starts first
db:
image: postgres:13
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=myapp
ports:
- "5432:5432" # Expose PostgreSQL port
volumes:
- postgres-data:/var/lib/postgresql/data # Persist database data
volumes:
postgres-data: # Named volume for database persistence
此檔案具有下列特性:
- 服務可以依名稱彼此參考 -例如,
db在 JDBC URL 中。 - Docker Compose 會自動建立服務的網路。
- Java 應用程式會因為
depends_on而等候資料庫啟動。 - 資料庫資料會使用具名磁碟區,在重新啟動後持續保留。
常見的 Docker Compose 命令
建立 compose.yml 檔案之後,請使用下列命令來管理您的應用程式:
# Build images without starting containers
docker compose build
# Start all services defined in compose.yml
docker compose up
# Start in detached mode (run in background)
docker compose up -d
# View running containers managed by compose
docker compose ps
# View logs from all containers
docker compose logs
# View logs from a specific service
docker compose logs app
# Stop all services
docker compose down
# Stop and remove volumes (useful for database resets)
docker compose down -v
開發工作流程
使用 Docker Compose 的一般 Java 開發工作流程包含下列步驟:
- 建立 compose.yml 檔案和 Dockerfile。
- 執行
docker compose up以啟動所有服務。 - 對 Java 程式代碼進行變更。
- 重建應用程式。 視設定而定,您可能需要重新啟動容器。
- 測試容器化環境中的變更。
- 當您完成時,請執行
docker compose down。
使用 Docker 執行單一容器
針對當您不需要多個互連服務的較簡單案例中,您可以使用 docker run 命令來啟動個別容器。
下列 Docker 命令適用於 Java 應用程式:
# Run a Java application JAR directly
docker run -p 8080:8080 myapp:latest
# Run with environment variables
docker run -p 8080:8080 -e "SPRING_PROFILES_ACTIVE=prod" myapp:latest
# Run in detached mode (background)
docker run -d -p 8080:8080 myapp:latest
# Run with a name for easy reference
docker run -d -p 8080:8080 --name my-java-app myapp:latest
# Run with volume mount for persistent data
docker run -p 8080:8080 -v ./data:/app/data myapp:latest
偵錯容器化應用程式
偵錯容器化 Java 應用程式有時很困難,因為您的程式代碼會在容器內的隔離環境中執行。
標準偵錯方法不一定會直接套用,但使用正確的組態,您可以建立應用程式的遠端偵錯連線。 本節說明如何設定容器以進行偵錯、將開發工具連線至執行容器,以及針對常見的容器相關問題進行疑難解答。
設定遠端偵錯
偵錯容器化 Java 應用程式需要公開偵錯埠,並設定 IDE 以連線到它。 您可以使用下列步驟來完成這些工作:
若要啟用偵錯,請修改 您的 Dockerfile ,使其包含下列內容:
備註
您可以修改容器的啟動指令。
FROM mcr.microsoft.com/java/jdk:21-zulu-ubuntu WORKDIR /app COPY target/*.jar app.jar EXPOSE 8080 5005 ENTRYPOINT ["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005", "-jar", "app.jar"]設定 Visual Studio Codelaunch.json檔案 以連線到偵錯埠,如下列範例所示:
{ "version": "0.2.0", "configurations": [ { "type": "java", "name": "Debug in Container", "request": "attach", "hostName": "localhost", "port": 5005 } ] }啟動容器時,將連接埠
5005對應至主機,然後在 Visual Studio Code 中啟動偵錯工具。
疑難排解容器問題
當容器未如預期般運作時,您可以檢查應用程式的記錄來調查問題。
使用下列命令來針對您的應用程式進行疑難解答。 在執行這些命令之前,請務必以您自己的值替換預留位置 (<...>)。
# View logs
docker logs <CONTAINER_ID>
# Follow logs in real-time
docker logs -f <CONTAINER_ID>
# Inspect container details
docker inspect <CONTAINER_ID>
# Get a shell in the container
docker exec -it <CONTAINER_ID> bash
針對 Java 特定問題,啟用 JVM 旗標以取得更好的診斷,如下列範例所示:
ENTRYPOINT ["java", "-XX:+PrintFlagsFinal", "-XX:+PrintGCDetails", "-jar", "app.jar"]
下表列出常見問題和對應的解決方案:
| 錯誤 | 可能的解決方案 |
|---|---|
| 記憶體不足 | 增加容器記憶體限制 |
| 連線逾時 | 檢查網路設定是否有錯誤。 確認埠和路由規則。 |
| 許可權問題 | 確認檔案系統許可權。 |
| Classpath 問題 | 檢查 JAR 結構和相依性。 |
優化Java容器
容器中的 Java 應用程式需要特別考慮以獲得最佳效能。 JVM 是在容器很常見之前所設計。 如果未正確設定容器,使用容器可能會導致資源配置問題。
您可以微調記憶體設定、優化映射大小,以及設定垃圾收集,大幅改善容器化 Java 應用程式的效能和效率。 本節涵蓋 Java 容器的基本優化,著重於記憶體管理、啟動時間和資源使用率。
容器中的 JVM 記憶體組態
JVM 不會自動偵測 Java 8 中的容器記憶體限制。 針對 Java 9+,預設會啟用容器感知。
設定 JVM 以遵守容器限制,如下列範例所示:
FROM mcr.microsoft.com/java/jre:21-zulu-ubuntu
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]
下列 JVM 旗標對於容器化應用程式而言很重要:
-
-XX:MaxRAMPercentage=75.0。 將堆積上限設定為可用記憶體的百分比。 -
-XX:InitialRAMPercentage=50.0。 設定初始堆積大小。 -
-Xmx與-Xms。 這些旗標也可供使用,但需要固定值。
為生產環境部署做準備
將容器化 Java 應用程式移至生產環境需要超越基本功能的考慮。
生產環境需要強大的安全性、可靠的監視、適當的資源配置,以及設定彈性。
本節涵蓋準備 Java 容器以供生產環境使用所需的基本做法和組態。 本節著重於安全性、健康情況檢查和組態管理,以確保應用程式在生產環境中可靠地執行。
安全性最佳做法
使用下列作法保護您的容器化 Java 應用程式:
預設安全性內容。 以非根使用者身分執行您的應用程式,如下列範例所示:
FROM mcr.microsoft.com/java/jre:21-zulu-ubuntu WORKDIR /app COPY target/*.jar app.jar RUN addgroup --system javauser && adduser --system --ingroup javauser javauser USER javauser ENTRYPOINT ["java", "-jar", "app.jar"]主動尋找問題。 使用下列命令定期掃描容器映像是否有弱點:
docker scan myapp:latest基底映像新鮮度。 將您的基底映像保持在最新狀態。
秘密管理。 實作適當的秘密管理。 例如,不要將敏感數據硬式編碼到您的應用程式,並盡可能使用密鑰保存庫。
受限的安全性內容。 將最低許可權原則套用至所有安全性內容。
檔案系統存取。 盡可能使用唯讀文件系統。
健康檢查和監測
使用 探針 監控應用程式的健康狀況,以確保您的應用程式正確執行。
對於 Spring Boot 應用程式,請加入 Actuator 相依性,以提供完整的健康狀態端點,如下列範例所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
設定您的應用程式以適合容器環境的格式輸出記錄,例如 JSON。
部署至 Azure 容器應用程式
本節將引導您準備適用於 Azure Container Apps 部署的 Java 容器,並醒目提示重要設定考慮。
為 Azure 準備您的容器
埠設定。 請確定您的容器會接聽 Azure 所提供的埠,如下列範例所示:
FROM mcr.microsoft.com/java/jre:21-zulu-ubuntu WORKDIR /app COPY target/*.jar app.jar ENV PORT=8080 EXPOSE ${PORT} CMD java -jar app.jar --server.port=${PORT}探查健康狀態。 針對 Azure 的存留性與就緒性檢查,實作健康狀態探查。
記錄組態。 將 記錄 設定為輸出至
stdout/stderr。為意外做好規劃。 使用逾時組態,正確設定妥善的正常關機處理。 如需詳細資訊,請參閱 Azure Container Apps 中的應用程式生命週期管理。