下载工作台
Spring Boot Web 开发

Docker/K8s 交付与 Java 框架选型

试读上半部分 · 解锁后可读全文

第 19 章 · Docker/K8s 交付与 Java 框架选型

本章目标:为 shop-spring-demo 编写多阶段 Dockerfile.dockerignore非 root 用户;使用 docker-compose.prod.yml 编排 app + Nginx + MySQL + Redis;理解 K8s 核心对象并阅读虚构 api.example.com YAML;全面对照 Spring Boot vs Django / Flask / FastAPI;回答面试框架选型;完成 19 章结业总结100 分进阶验收表(选修);说明与 spring-cloud-webxiaozi-cloud 衔接。

学时建议:6~8 小时(含 3 小时容器演练)

前置ch11 jar 部署;ch18 可观测性;ch10 Redis。微服务深度见 spring-cloud-web;K8s 运维见 xiaozi-cloud


19.1 从「能跑」到「可交付」

源码 ──mvn package──► docker build ──► registry.example.com/shop-spring:1.0.0
                                              │
                                              ▼
                                    K8s Deployment / compose
                                              api.example.com
交付物说明
可执行 jarspring-boot-maven-plugin 胖 jar
Docker 镜像不可变制品,含 JRE 与应用
compose / K8s YAML拓扑与配置
.env.example文档化变量,不含密钥
虚构 shop-spring-demoapi.example.comregistry.example.com严禁真实镜像仓库凭证、Kubeconfig、数据库密码。

19.2 多阶段 Dockerfile

shop-spring-demo/Dockerfile

# ── 构建阶段 ──
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /build
COPY pom.xml mvnw ./
COPY .mvn .mvn
RUN ./mvnw -q -DskipTests dependency:go-offline
COPY src ./src
RUN ./mvnw -q -DskipTests package

# ── 运行阶段 ──
FROM eclipse-temurin:21-jre-alpine AS runtime
RUN addgroup -g 1000 app && adduser -u 1000 -G app -D app
WORKDIR /app
COPY --from=builder /build/target/shop-spring-demo-*.jar app.jar
USER app
EXPOSE 8080
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s \
  CMD wget -qO- http://127.0.0.1:8080/actuator/health || exit 1
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

.dockerignore

target/
.git/
.idea/
*.iml
.env
logs/
实践原因
多阶段镜像不含 JDK 与源码
非 root降低容器逃逸风险
MaxRAMPercentageK8s 内存 limit 下自适应堆
HEALTHCHECK配合 orchestrator 探针

19.3 docker-compose.prod.yml

services:
  app:
    image: registry.example.com/shop-spring:1.0.0
    environment:
      SPRING_PROFILES_ACTIVE: prod
      DB_HOST: mysql
      DB_PASSWORD: ${DB_PASSWORD}
      REDIS_HOST: redis
    depends_on:
      mysql: { condition: service_healthy }
      redis: { condition: service_started }
    ports: ["8080:8080"]

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: shop_spring
      MYSQL_USER: shop_spring
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    volumes: [mysql_data:/var/lib/mysql]
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    ports: ["6379:6379"]

  nginx:
    image: nginx:1.25-alpine
    ports: ["443:443", "80:80"]
    volumes:
      - ./nginx/api.example.com.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on: [app]

volumes:
  mysql_data:

Nginx 反代片段(虚构域名):

server {
    listen 443 ssl;
    server_name api.example.com;
    location / {
        proxy_pass http://app:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    location /actuator/prometheus {
        allow 10.0.0.0/8;
        deny all;
        proxy_pass http://app:9090;
    }
}

19.4 Kubernetes 核心对象

k8s/deployment.yaml(教学简化):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: shop-spring
  namespace: shop-demo
spec:
  replicas: 2
  selector:
    matchLabels: { app: shop-spring }
  template:
    metadata:
      labels: { app: shop-spring }
    spec:
      containers:
        - name: app
          image: registry.example.com/shop-spring:1.0.0

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。