Java 部署教學:Spring Boot 應用程式部署方案【2025】

Java 部署教學:Spring Boot 應用程式部署方案

Java 和 Spring Boot 是企業級應用開發的主力選擇。雖然 Java 應用的啟動時間和記憶體佔用相對較高,但其穩定性、效能和豐富的生態系統,使它在生產環境中廣受歡迎。

這篇教學將帶你從打包 Spring Boot 應用開始,到 Docker 容器化、JVM 調優,最後部署到各大雲端平台。無論你是剛接觸 Java 部署,還是想優化現有的部署流程,都能找到實用的技巧。

如果你想了解更完整的部署策略,可以先閱讀 程式部署完整指南


Spring Boot 打包基礎

spring-boot-packaging

插圖:Spring Boot 打包流程圖

場景描述:
Technical illustration showing Spring Boot 打包流程圖. Clean, professional diagram style.

視覺重點:
- Clear presentation of the concept
- Professional technical diagram style
- Easy to understand visual elements

必須出現的元素:
- Relevant technical components
- Clear labels and annotations
- Logical flow or structure

需要顯示的中文字:

風格:
Clean flat design, technical illustration, modern infographic style

顏色調性:
Professional blues and grays, with accent colors for emphasis

避免元素:
Cluttered design, realistic photos, complex 3D rendering

Spring Boot 最大的特點是可以打包成「可執行的 Fat JAR」,內嵌 Tomcat/Jetty 伺服器,只需要 java -jar 就能執行。

什麼是 Fat JAR

傳統的 Java Web 應用需要部署到 Tomcat 等應用伺服器。但 Spring Boot 的 Fat JAR(或稱 Uber JAR)包含了:

  • 你的應用程式碼
  • 所有相依的 JAR 檔案
  • 內嵌的 Servlet 容器(Tomcat/Jetty/Undertow)
  • Spring Boot Loader

這意味著只要有 JRE,就能直接執行:

java -jar my-application.jar

專案結構

典型的 Spring Boot 專案結構:

my-spring-app/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/demo/
│   │   │       ├── DemoApplication.java
│   │   │       ├── controller/
│   │   │       ├── service/
│   │   │       └── repository/
│   │   └── resources/
│   │       ├── application.properties
│   │       ├── application-prod.properties
│   │       └── static/
│   └── test/
├── pom.xml              # Maven
├── build.gradle         # Gradle
├── Dockerfile
└── README.md

Maven vs Gradle 打包

maven-vs-gradle

插圖:Maven vs Gradle 比較圖

場景描述:
Technical illustration showing Maven vs Gradle 比較圖. Clean, professional diagram style.

視覺重點:
- Clear presentation of the concept
- Professional technical diagram style
- Easy to understand visual elements

必須出現的元素:
- Relevant technical components
- Clear labels and annotations
- Logical flow or structure

需要顯示的中文字:

風格:
Clean flat design, technical illustration, modern infographic style

顏色調性:
Professional blues and grays, with accent colors for emphasis

避免元素:
Cluttered design, realistic photos, complex 3D rendering

Spring Boot 支援 Maven 和 Gradle 兩種建置工具,各有優缺點。

Maven 打包

pom.xml 範例

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <properties>
        <java.version>21</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

打包命令

# 清理並打包(跳過測試)
mvn clean package -DskipTests

# 打包並執行測試
mvn clean package

# 產出位置
# target/demo-1.0.0.jar

Gradle 打包

build.gradle 範例

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '1.0.0'

java {
    sourceCompatibility = '21'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

打包命令

# 清理並打包(跳過測試)
./gradlew clean build -x test

# 打包並執行測試
./gradlew clean build

# 產出位置
# build/libs/demo-1.0.0.jar

Maven vs Gradle 比較

項目 Maven Gradle
設定語法 XML(冗長但明確) Groovy/Kotlin DSL(簡潔)
建置速度 較慢 快(增量建置、快取)
學習曲線
生態系統 最成熟 成長中
企業使用 主流 漸增

選擇建議
- 新專案或追求效能 → Gradle
- 企業環境、團隊熟悉 → Maven

💡 VPS 設定太複雜?

Java 應用的部署涉及 JVM 調優、記憶體設定、反向代理等配置。

預約免費諮詢,讓我們幫你處理伺服器設定。


JVM 調優:生產環境設定

jvm-memory-model

插圖:JVM 記憶體模型圖

場景描述:
Technical illustration showing JVM 記憶體模型圖. Clean, professional diagram style.

視覺重點:
- Clear presentation of the concept
- Professional technical diagram style
- Easy to understand visual elements

必須出現的元素:
- Relevant technical components
- Clear labels and annotations
- Logical flow or structure

需要顯示的中文字:

風格:
Clean flat design, technical illustration, modern infographic style

顏色調性:
Professional blues and grays, with accent colors for emphasis

避免元素:
Cluttered design, realistic photos, complex 3D rendering

Java 應用的效能很大程度取決於 JVM 參數設定。正確的調優可以避免 OutOfMemoryError、減少 GC 暫停時間。

記憶體設定

# 基本記憶體設定
java -Xms512m -Xmx1024m -jar app.jar

# 參數說明
# -Xms:初始 Heap 大小
# -Xmx:最大 Heap 大小

記憶體設定建議

可用記憶體 -Xms -Xmx 適用場景
1 GB 256m 512m 小型 API
2 GB 512m 1024m 標準應用
4 GB 1024m 2048m 中型應用
8 GB+ 2048m 4096m 大型應用

重要原則
- 將 -Xms-Xmx 設為相同值,避免動態調整的開銷
- 不要將 -Xmx 設為 100% 可用記憶體,需保留給 Metaspace、Stack、Native Memory

GC 設定

Java 21 預設使用 G1 GC,適合大多數情況:

# 使用 G1 GC(預設)
java -XX:+UseG1GC -jar app.jar

# 設定 GC 暫停時間目標(毫秒)
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar app.jar

# 高吞吐量場景(接受較長暫停)
java -XX:+UseParallelGC -jar app.jar

# 低延遲場景(ZGC,Java 15+)
java -XX:+UseZGC -jar app.jar

完整的生產環境 JVM 參數

java \
  -Xms1024m \
  -Xmx1024m \
  -XX:+UseG1GC \
  -XX:MaxGCPauseMillis=200 \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=/var/log/heapdump.hprof \
  -Dspring.profiles.active=prod \
  -Dserver.port=8080 \
  -jar app.jar
參數 說明
-XX:+HeapDumpOnOutOfMemoryError OOM 時自動產生 Heap Dump
-XX:HeapDumpPath Heap Dump 存放路徑
-Dspring.profiles.active Spring Profile
-Dserver.port 應用程式 port

application.properties 生產設定

# application-prod.properties

# 伺服器設定
server.port=${PORT:8080}
server.shutdown=graceful

# Actuator 健康檢查
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=when_authorized

# 連線池設定(HikariCP)
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.connection-timeout=20000

# 日誌設定
logging.level.root=INFO
logging.level.com.example=INFO
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n

Docker 容器化部署

java-docker-multistage

插圖:Java Docker 多階段建置圖

場景描述:
Technical illustration showing Java Docker 多階段建置圖. Clean, professional diagram style.

視覺重點:
- Clear presentation of the concept
- Professional technical diagram style
- Easy to understand visual elements

必須出現的元素:
- Relevant technical components
- Clear labels and annotations
- Logical flow or structure

需要顯示的中文字:

風格:
Clean flat design, technical illustration, modern infographic style

顏色調性:
Professional blues and grays, with accent colors for emphasis

避免元素:
Cluttered design, realistic photos, complex 3D rendering

Docker 容器化是 Java 應用部署的最佳實踐,可以確保環境一致性並簡化部署流程。

選擇正確的基礎映像

映像 大小 說明
eclipse-temurin:21-jdk ~450MB 包含 JDK,用於建置
eclipse-temurin:21-jre ~270MB 只有 JRE,用於執行
eclipse-temurin:21-jre-alpine ~180MB Alpine 版本,更小
amazoncorretto:21 ~400MB Amazon 維護的 OpenJDK
azul/zulu-openjdk:21 ~350MB Azul 維護的 OpenJDK

建議:生產環境使用 eclipse-temurin:21-jre-alpineeclipse-temurin:21-jre

基本 Dockerfile

FROM eclipse-temurin:21-jre-alpine

WORKDIR /app

# 複製 JAR 檔案
COPY target/*.jar app.jar

# 開放 port
EXPOSE 8080

# JVM 參數
ENV JAVA_OPTS="-Xms512m -Xmx512m"

# 啟動命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

多階段建置 Dockerfile(推薦)

# 階段一:建置
FROM eclipse-temurin:21-jdk-alpine AS builder

WORKDIR /app

# 複製 Maven 設定(利用 Docker 快取)
COPY pom.xml .
COPY .mvn .mvn
COPY mvnw .

# 下載相依套件(這層會被快取)
RUN ./mvnw dependency:go-offline -B

# 複製原始碼
COPY src src

# 建置(跳過測試)
RUN ./mvnw package -DskipTests -B

# 階段二:執行
FROM eclipse-temurin:21-jre-alpine AS production

WORKDIR /app

# 安全性:建立非 root 使用者
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring

# 從建置階段複製 JAR
COPY --from=builder /app/target/*.jar app.jar

# 開放 port
EXPOSE 8080

# 健康檢查
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1

# JVM 參數
ENV JAVA_OPTS="-Xms512m -Xmx512m -XX:+UseG1GC"

# 啟動命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar app.jar"]

Gradle 版本的多階段 Dockerfile

# 階段一:建置
FROM eclipse-temurin:21-jdk-alpine AS builder

WORKDIR /app

COPY build.gradle settings.gradle ./
COPY gradle gradle
COPY gradlew .

RUN ./gradlew dependencies --no-daemon

COPY src src

RUN ./gradlew build -x test --no-daemon

# 階段二:執行
FROM eclipse-temurin:21-jre-alpine AS production

WORKDIR /app

RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring

COPY --from=builder /app/build/libs/*.jar app.jar

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1

ENV JAVA_OPTS="-Xms512m -Xmx512m -XX:+UseG1GC"

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

建置並執行

# 建置 Image
docker build -t my-spring-app:1.0.0 .

# 執行容器
docker run -d \
  -p 8080:8080 \
  -e JAVA_OPTS="-Xms512m -Xmx1024m" \
  -e SPRING_PROFILES_ACTIVE=prod \
  -e DATABASE_URL=jdbc:postgresql://... \
  --name my-app \
  my-spring-app:1.0.0

# 查看日誌
docker logs -f my-app

想了解更多 Docker 部署細節,請參考 Docker Deploy 教學

💡 不確定該選哪個雲端平台?

AWS、GCP、Azure 各有優勢,選錯可能增加成本或維運負擔。

預約免費諮詢,讓專家幫你評估最適合的部署方案。


雲端平台部署

java-cloud-deployment

插圖:Java 雲端部署選項圖

場景描述:
Technical illustration showing Java 雲端部署選項圖. Clean, professional diagram style.

視覺重點:
- Clear presentation of the concept
- Professional technical diagram style
- Easy to understand visual elements

必須出現的元素:
- Relevant technical components
- Clear labels and annotations
- Logical flow or structure

需要顯示的中文字:

風格:
Clean flat design, technical illustration, modern infographic style

顏色調性:
Professional blues and grays, with accent colors for emphasis

避免元素:
Cluttered design, realistic photos, complex 3D rendering

各大雲端平台都有對 Java/Spring Boot 的良好支援,以下介紹幾種常見的部署方式。

Railway 部署(最簡單)

Railway 會自動偵測 Java 專案並使用正確的 JDK 版本。

1. 建立 system.properties

java.runtime.version=21

2. 連接 GitHub 部署

Railway 會自動執行 mvn clean packagegradle build,然後執行 JAR。

3. 設定環境變數

JAVA_OPTS=-Xms512m -Xmx512m
SPRING_PROFILES_ACTIVE=prod
DATABASE_URL=postgresql://...

GCP Cloud Run 部署

# 建置 Docker Image
docker build -t gcr.io/PROJECT_ID/my-spring-app:1.0.0 .

# 推送到 GCR
docker push gcr.io/PROJECT_ID/my-spring-app:1.0.0

# 部署到 Cloud Run
gcloud run deploy my-spring-app \
  --image gcr.io/PROJECT_ID/my-spring-app:1.0.0 \
  --platform managed \
  --region asia-east1 \
  --memory 1Gi \
  --cpu 1 \
  --min-instances 0 \
  --max-instances 10 \
  --set-env-vars "SPRING_PROFILES_ACTIVE=prod" \
  --allow-unauthenticated

Cloud Run 注意事項
- Java 應用啟動較慢,建議設定 --min-instances 1 避免冷啟動
- 記憶體至少設定 512Mi,建議 1Gi

AWS Elastic Beanstalk 部署

1. 準備 Procfile

web: java -Xms512m -Xmx512m -jar target/demo-1.0.0.jar --server.port=5000

2. 使用 EB CLI 部署

# 初始化
eb init -p java-21-corretto my-spring-app

# 建立環境
eb create production-env

# 部署更新
eb deploy

# 設定環境變數
eb setenv SPRING_PROFILES_ACTIVE=prod DATABASE_URL=jdbc:...

3. 或使用 .ebextensions 設定

# .ebextensions/01-jvm.config
option_settings:
  aws:elasticbeanstalk:application:environment:
    JAVA_OPTS: "-Xms512m -Xmx1024m -XX:+UseG1GC"
    SPRING_PROFILES_ACTIVE: "prod"

Azure App Service 部署

# 安裝 Azure CLI 並登入
az login

# 建立 App Service Plan
az appservice plan create \
  --name my-plan \
  --resource-group my-group \
  --sku B1 \
  --is-linux

# 建立 Web App
az webapp create \
  --name my-spring-app \
  --resource-group my-group \
  --plan my-plan \
  --runtime "JAVA:21-java21"

# 部署 JAR
az webapp deploy \
  --resource-group my-group \
  --name my-spring-app \
  --src-path target/demo-1.0.0.jar \
  --type jar

# 設定環境變數
az webapp config appsettings set \
  --resource-group my-group \
  --name my-spring-app \
  --settings SPRING_PROFILES_ACTIVE=prod

平台比較

平台 難度 費用 Java 支援 適用場景
Railway $5/月起 21 Side Project、小型應用
Cloud Run ⭐⭐ 按用量 任意(Docker) API、微服務
Elastic Beanstalk ⭐⭐⭐ 依 EC2 21 企業應用、AWS 整合
Azure App Service ⭐⭐ $13/月起 21 .NET + Java 混合
Kubernetes ⭐⭐⭐⭐ 依規模 任意 大規模、微服務

VPS 部署(傳統方式)

如果你需要完全掌控伺服器環境,可以在 VPS 上手動部署。

安裝 Java

# Ubuntu/Debian
sudo apt update
sudo apt install openjdk-21-jre-headless

# Amazon Linux
sudo yum install java-21-amazon-corretto-headless

# 確認安裝
java -version

使用 systemd 管理服務

建立 /etc/systemd/system/my-spring-app.service

[Unit]
Description=My Spring Boot Application
After=network.target

[Service]
Type=simple
User=spring
Group=spring

Environment="JAVA_OPTS=-Xms512m -Xmx1024m -XX:+UseG1GC"
Environment="SPRING_PROFILES_ACTIVE=prod"

ExecStart=/usr/bin/java $JAVA_OPTS -jar /opt/my-app/app.jar
ExecStop=/bin/kill -SIGTERM $MAINPID

Restart=always
RestartSec=10

# 日誌
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

啟動服務

# 重新載入 systemd
sudo systemctl daemon-reload

# 啟動服務
sudo systemctl start my-spring-app

# 設定開機自動啟動
sudo systemctl enable my-spring-app

# 查看狀態
sudo systemctl status my-spring-app

# 查看日誌
sudo journalctl -u my-spring-app -f

Nginx 反向代理

# /etc/nginx/sites-available/my-spring-app
server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket 支援
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # 超時設定
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # Actuator 端點限制存取
    location /actuator {
        deny all;
        # 或只允許特定 IP
        # allow 10.0.0.0/8;
        # deny all;
    }
}

Spring Boot Actuator 健康檢查

Spring Boot Actuator 提供生產環境必備的監控端點。

啟用 Actuator

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

設定暴露的端點

# application.properties
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=when_authorized
management.endpoint.health.probes.enabled=true

健康檢查端點

端點 用途
/actuator/health 整體健康狀態
/actuator/health/liveness 存活探針(K8s 用)
/actuator/health/readiness 就緒探針(K8s 用)
/actuator/info 應用程式資訊
/actuator/metrics 指標數據

FAQ 常見問題

Q1: Spring Boot 啟動太慢怎麼辦?

  1. 使用 Spring Boot 3.2+ 的 Virtual Threads
  2. 使用 GraalVM Native Image(大幅加速啟動)
  3. 減少不必要的 Auto-Configuration
  4. 使用 lazy initialization
spring.main.lazy-initialization=true

Q2: 記憶體不足(OOM)怎麼處理?

  1. 增加 -Xmx 設定
  2. 檢查是否有記憶體洩漏
  3. 使用 -XX:+HeapDumpOnOutOfMemoryError 產生 dump 分析
  4. 檢查連線池設定是否過大

Q3: 如何優雅關閉(Graceful Shutdown)?

# application.properties
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=30s

Q4: Docker 中 Java 應用記憶體設定?

Java 10+ 會自動偵測容器記憶體限制。但建議明確設定:

ENV JAVA_OPTS="-XX:MaxRAMPercentage=75.0"

這會使用容器記憶體限制的 75% 作為最大 Heap。

Q5: 如何實現零停機部署?

  • Kubernetes:使用 Rolling Update 策略
  • Elastic Beanstalk:使用 Rolling 或 Immutable 更新
  • 傳統 VPS:使用 Nginx upstream + 兩個實例輪換

Java Spring Boot 部署方案重點整理

這篇教學涵蓋了 Java/Spring Boot 應用的完整部署流程:

  • 打包方式:Maven vs Gradle 的差異與使用
  • JVM 調優:記憶體設定、GC 選擇、生產環境參數
  • Docker 容器化:多階段建置、基礎映像選擇
  • 雲端部署:Railway、Cloud Run、Elastic Beanstalk、Azure
  • VPS 部署:systemd 服務、Nginx 反向代理

Java 應用雖然啟動較慢、記憶體佔用較高,但其穩定性和效能在生產環境中經得起考驗。選擇合適的部署方式,配合正確的 JVM 調優,就能讓你的 Spring Boot 應用穩定運行。

如果你想了解如何在 Kubernetes 上部署 Java 應用,可以接著閱讀 Kubernetes Deploy 教學


Java 部署需要協助?

從 JVM 調優到雲端架構規劃,Java 生產部署有許多專業細節。

預約免費諮詢,讓 VibeFix 的工程師幫你把 Spring Boot 專案順利上線!

分享文章:
V

VibeFix

專門解決 AI Vibe Coding 後的疑難雜症,讓你的專案順利上線。

這篇文章有幫到你嗎?

如果還有問題,讓我們直接幫你解決!

聯繫我們