Kotlin: Kotlin项目部署详解
最后更新:2026-08-26
代码写完了,最后一英里——Charlie 将 OrderProcessor 容器化、编排 CI/CD 流水线、配置监控告警,从 到生产上线全自动化。
1. 你将学到
- Docker 多阶段构建: → 轻量 JRE 镜像
- Docker Compose:OrderProcessor + PostgreSQL + Redis
- CI/CD:GitHub Actions 构建、测试、推送镜像
- 监控:Micrometer + Prometheus + Grafana 指标看板
- Charlie 实战:一键部署 + 健康检查 + 生产就绪清单
2. 一个架构师的真实故事
(1) 痛点:手动部署的人肉流水线
Charlie 的团队手动部署:SSH 到服务器 → → → → 。一次部署 30 分钟,每月 2-3 次人为失误。
(2) CI/CD 全自动化的解法
TEXT
📖 仅展示
Before: git push → SSH → build → deploy (30 min, error-prone)
After: git push → GitHub Actions → Docker build → deploy (5 min, zero-touch)
容器化 + CI/CD = 部署从 30 分钟人肉操作变为 5 分钟全自动流水线。
3. Docker 多阶段构建
(1) Dockerfile
DOCKERFILE
# Stage 1: Build
FROM gradle:8.5-jdk17 AS builder
WORKDIR /app
COPY build.gradle.kts settings.gradle.kts ./
COPY gradle ./gradle
COPY src ./src
RUN gradle bootJar --no-daemon -x test
# Stage 2: Runtime (lightweight JRE)
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
# Non-root user for security
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-jar", "app.jar"]
(2) 多阶段构建对比
| 维度 | 单阶段 | 多阶段 |
|---|---|---|
| 镜像大小 | ~800MB (JDK + source) | ~150MB (JRE only) |
| 安全性 | 源码在镜像中 | 源码不进入运行镜像 |
| 构建缓存 | 无分层 | 每层独立缓存 |
| 构建时间 | 每次全量 | 依赖层缓存复用 |
4. Docker Compose 编排
(1) docker-compose.yml
YAML
version: '3.8'
services:
order-processor:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_DATASOURCE_URL=r2dbc:postgresql://postgres:5432/orderdb
- SPRING_DATASOURCE_USERNAME=order_user
- SPRING_DATASOURCE_PASSWORD=order_pass
- SPRING_REDIS_HOST=redis
- MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE=health,info,prometheus
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- order-net
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_DB=orderdb
- POSTGRES_USER=order_user
- POSTGRES_PASSWORD=order_pass
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U order_user -d orderdb"]
interval: 5s
timeout: 5s
retries: 5
networks:
- order-net
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
networks:
- order-net
prometheus:
image: prom/prometheus:latest
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
networks:
- order-net
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
- order-net
volumes:
pgdata:
networks:
order-net:
driver: bridge
(2) 一键部署
BASH
# Start all services
docker-compose up -d
# Check status
docker-compose ps
# View logs
docker-compose logs -f order-processor
# Stop all
docker-compose down
5. CI/CD 流水线
(1) GitHub Actions
YAML
# .github/workflows/deploy.yml
name: Build and Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v3
with:
path: ~/.gradle/caches
key: gradle-${{ hashFiles('**/*.gradle.kts') }}
- name: Run tests
run: ./gradlew test
- name: Build JAR
run: ./gradlew bootJar
- name: Build Docker image
run: docker build -t order-processor:${{ github.sha }} .
- name: Push to registry
if: github.ref == 'refs/heads/main'
run: |
docker tag order-processor:${{ github.sha }} registry.example.com/order-processor:latest
docker push registry.example.com/order-processor:latest
- name: Deploy
if: github.ref == 'refs/heads/main'
run: |
ssh deploy@prod-server "docker pull registry.example.com/order-processor:latest && docker-compose up -d"
(2) CI/CD 流水线图
flowchart TD
A[git push] --> B[GitHub Actions]
B --> C[Checkout Code]
C --> D[Setup JDK 17]
D --> E[Cache Gradle]
E --> F[Run Tests]
F --> G{Tests Pass?}
G -->|Yes| H[Build JAR]
G -->|No| I[Notify Team]
H --> J[Build Docker Image]
J --> K{Main Branch?}
K -->|Yes| L[Push to Registry]
K -->|No| M[Stop]
L --> N[Deploy to Production]
N --> O[Health Check]
O --> P{Healthy?}
P -->|Yes| Q[Live]
P -->|No| R[Rollback]
6. 监控
(1) Spring Boot Actuator 配置
KOTLIN
// application.yml
// management:
// endpoints:
// web:
// exposure:
// include: health,info,prometheus,metrics
// metrics:
// export:
// prometheus:
// enabled: true
// endpoint:
// health:
// show-details: always
(2) Micrometer 自定义指标
KOTLIN
import io.micrometer.core.instrument.Counter
import io.micrometer.core.instrument.MeterRegistry
import io.micrometer.core.instrument.Timer
class OrderMetrics(registry: MeterRegistry) {
private val ordersCreated = Counter.builder("orders.created.total")
.description("Total orders created")
.register(registry)
private val orderProcessingTime = Timer.builder("orders.processing.time")
.description("Order processing time")
.register(registry)
fun recordOrderCreated() { ordersCreated.increment() }
fun `<T>` recordProcessingTime(block: () -> T): T {
return orderProcessingTime.recordCallable { block() } ?: block()
}
}
(3) 监控指标
| 指标 | 类型 | 告警阈值 |
|---|---|---|
| Counter | - | |
| Timer | P99 > 2s | |
| Gauge | > 80% | |
| Gauge | > 90% | |
| Timer | P99 > 5s | |
| / | Gauge | Free < 10% |
7. 健康检查与生产就绪
(1) 健康检查端点
KOTLIN
// Spring Boot Actuator health endpoint
// GET /actuator/health
// {
// "status": "UP",
// "components": {
// "db": { "status": "UP" },
// "redis": { "status": "UP" },
// "diskSpace": { "status": "UP" }
// }
// }
(2) 生产就绪清单
| 类别 | 检查项 | 状态 |
|---|---|---|
| 安全 | 非 root 用户运行 | ☐ |
| 安全 | 无硬编码密钥 | ☐ |
| 安全 | HTTPS 配置 | ☐ |
| 可靠性 | 健康检查端点 | ☐ |
| 可靠性 | 优雅关闭(SIGTERM) | ☐ |
| 可靠性 | 数据库连接池配置 | ☐ |
| 可观测 | 日志结构化输出 | ☐ |
| 可观测 | Prometheus 指标暴露 | ☐ |
| 可观测 | 告警规则配置 | ☐ |
| 性能 | JVM 堆大小配置 | ☐ |
| 性能 | GC 策略选择 | ☐ |
| 部署 | Docker 镜像 < 200MB | ☐ |
| 部署 | CI/CD 流水线 | ☐ |
| 部署 | 回滚策略 | ☐ |
8. 完整示例:一键部署演示
KOTLIN
// ============================================
// OrderProcessor - Deployment Simulation
// Feature: Docker + CI/CD + Health check demo
// ============================================
import kotlin.system.measureTimeMillis
data class DeployResult(val service: String, val status: String, val time: Long)
class DeploySimulator {
private val services = mutableListOf`<DeployResult>`()
private var deployed = false
fun build(): DeploySimulator {
print(" Building Docker image...")
val time = measureTimeMillis { Thread.sleep(800) }
println(" Done (${time}ms)")
return this
}
fun test(): DeploySimulator {
print(" Running tests...")
val time = measureTimeMillis { Thread.sleep(300) }
println(" Passed (${time}ms)")
return this
}
fun push(): DeploySimulator {
print(" Pushing to registry...")
val time = measureTimeMillis { Thread.sleep(500) }
println(" Done (${time}ms)")
return this
}
fun deploy(service: String, port: Int): DeploySimulator {
print(" Deploying $service on port $port...")
val time = measureTimeMillis { Thread.sleep(400) }
services.add(DeployResult(service, "RUNNING", time))
println(" Running (${time}ms)")
return this
}
fun healthCheck(): DeploySimulator {
print(" Health check...")
val time = measureTimeMillis { Thread.sleep(200) }
val allHealthy = services.all { it.status == "RUNNING" }
println(if (allHealthy) " ALL HEALTHY" else " UNHEALTHY DETECTED")
return this
}
fun summary() {
println("\n=== Deployment Summary ===")
services.forEach { s ->
println(" ${s.service}: ${s.status} (${s.time}ms)")
}
println("\n Total services: ${services.size}")
println(" Health: ${if (services.all { it.status == "RUNNING" }) "ALL GREEN" else "ISSUES DETECTED"}")
deployed = true
}
fun isDeployed() = deployed
}
fun main() {
println("=== OrderProcessor CI/CD Pipeline ===\n")
println("[1/6] Build Stage:")
DeploySimulator()
.build()
.test()
println("\n[2/6] Push Stage:")
DeploySimulator().push()
println("\n[3/6] Deploy Stage:")
val deployer = DeploySimulator()
.deploy("postgres", 5432)
.deploy("redis", 6379)
.deploy("order-processor", 8080)
.deploy("prometheus", 9090)
.deploy("grafana", 3000)
println("\n[4/6] Health Check:")
deployer.healthCheck()
println("\n[5/6] Smoke Test:")
println(" GET /actuator/health -> 200 OK")
println(" GET /api/v1/orders -> 200 OK")
println("\n[6/6] Production Ready Checklist:")
val checks = listOf(
"Non-root user" to true,
"No hardcoded secrets" to true,
"Health endpoint exposed" to true,
"Prometheus metrics enabled" to true,
"Graceful shutdown configured" to true,
"Docker image < 200MB" to true,
"CI/CD pipeline active" to true,
"Rollback strategy defined" to true
)
checks.forEach { (item, passed) ->
println(" ${if (passed) "✅" else "❌"} $item")
}
val passCount = checks.count { it.second }
println("\n Result: $passCount/${checks.size} checks passed")
if (passCount == checks.size) {
println("\n 🚀 OrderProcessor is LIVE!")
}
}
输出:
TEXT
📖 仅展示
=== OrderProcessor CI/CD Pipeline ===
[1/6] Build Stage:
Building Docker image... Done (804ms)
Running tests... Passed (301ms)
[2/6] Push Stage:
Pushing to registry... Done (502ms)
[3/6] Deploy Stage:
Deploying postgres on port 5432... Running (401ms)
Deploying redis on port 6379... Running (401ms)
Deploying order-processor on port 8080... Running (401ms)
Deploying prometheus on port 9090... Running (401ms)
Deploying grafana on port 3000... Running (401ms)
[4/6] Health Check:
Health check... ALL HEALTHY
[5/6] Smoke Test:
GET /actuator/health -> 200 OK
GET /api/v1/orders -> 200 OK
[6/6] Production Ready Checklist:
✅ Non-root user
✅ No hardcoded secrets
✅ Health endpoint exposed
✅ Prometheus metrics enabled
✅ Graceful shutdown configured
✅ Docker image < 200MB
✅ CI/CD pipeline active
✅ Rollback strategy defined
Result: 8/8 checks passed
🚀 OrderProcessor is LIVE!
❓ 常见问题
Q Docker 多阶段构建的好处是什么?
A 最终镜像只包含运行时依赖(JRE),不含源码和构建工具,镜像从 800MB 降到 150MB,攻击面更小,启动更快。
Q 如何实现零停机部署?
A 蓝绿部署或滚动更新。蓝绿部署维护两个环境交替切换;滚动更新逐个替换实例。Kubernetes 原生支持滚动更新。
Q 如何回滚失败的部署?
A Docker 镜像每次构建打 Git SHA 标签,回滚只需 。CI/CD 自动回滚更理想。
Q 密钥怎么管理?
A 不用环境变量或配置文件存密钥。使用 Vault、AWS Secrets Manager 或 Kubernetes Secrets。CI/CD 从密钥管理器注入。
Q 如何监控 JVM 应用?
A Spring Boot Actuator + Micrometer + Prometheus + Grafana 是标准组合。JVM 特有指标:堆内存、GC 次数/时间、线程数。
Q 生产环境的 JVM 参数怎么设?
A 和 设相同值(避免堆扩容开销),用 G1GC(),容器环境加 。
📖 小节
- Docker 多阶段构建:构建阶段用 JDK,运行阶段用 JRE,镜像从 800MB 降到 150MB
- Docker Compose 一键编排:应用 + 数据库 + 缓存 + 监控
- CI/CD 流水线:git push → 测试 → 构建 → 推送 → 部署,5 分钟全自动
- Micrometer + Prometheus + Grafana:指标采集、存储、可视化三位一体
- 生产就绪清单:安全、可靠性、可观测、性能、部署——8 项必检
- 健康检查是生产底线: 端点 + Docker HEALTHCHECK
📝 作业
- 基础题(难度⭐):为 OrderProcessor 编写 Dockerfile(单阶段即可),基于 。提示:
- 进阶题(难度⭐⭐):编写 docker-compose.yml,包含 OrderProcessor + PostgreSQL,配置健康检查。提示:
- 挑战题(难度⭐⭐⭐):编写完整的 GitHub Actions CI/CD 流水线,包含构建、测试、Docker 推送和部署步骤。提示: