Deployment Patterns — Docker, K8s, CI/CD
Quick Decision Matrix
| Need |
Reference |
When to read |
| Dockerfile |
references/dockerfile.md |
Creating/reviewing Docker images |
| K8s manifests |
references/kubernetes.md |
Writing Deployment, Service, HPA, ConfigMap |
| CI/CD pipeline |
references/cicd.md |
Setting up GitHub Actions or GitLab CI |
| Health probes |
references/health-probes.md |
Configuring liveness/readiness/startup probes |
| Generate Dockerfile |
scripts/generate-dockerfile.sh |
Scaffold a production Dockerfile |
Core Principles
- Separate build/runtime — multi-stage builds (JDK build, JRE runtime)
- Never root —
USER appuser in production images
- Container-aware JVM —
-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0
- Probe semantics — liveness = internal only, readiness = external deps
- Graceful shutdown —
terminationGracePeriodSeconds > timeout-per-shutdown-phase
- No secrets in images — K8s Secrets, SealedSecrets, or Vault
Dockerfile Essentials
# Build
FROM eclipse-temurin:17-jdk-jammy AS builder
WORKDIR /app
COPY gradle/ gradle/
COPY gradlew build.gradle.kts settings.gradle.kts ./
RUN ./gradlew dependencies --no-daemon || true
COPY src/ src/
RUN ./gradlew bootJar --no-daemon -x test
# Runtime
FROM eclipse-temurin:17-jre-jammy
RUN groupadd -r appuser && useradd -r -g appuser appuser
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
USER appuser
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=50.0"
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
Layered JAR, Maven, JVM flags → references/dockerfile.md.
Health Probes Summary
# application.yml
management:
endpoint.health:
probes.enabled: true
group:
liveness:
include: livenessState
readiness:
include: readinessState, db, redis
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
| Probe |
Endpoint |
Checks |
Failure → |
| Liveness |
/actuator/health/liveness |
App alive |
Pod restart |
| Readiness |
/actuator/health/readiness |
DB, Redis |
Remove from Service |
| Startup |
/actuator/health/liveness |
Init done |
Wait |
Custom HealthIndicators, composite readiness, shutdown sequence → references/health-probes.md.
Resource Sizing
| Type |
Mem Request |
Mem Limit |
CPU Request |
CPU Limit |
| Lightweight API |
256Mi |
512Mi |
100m |
500m |
| Standard API |
512Mi |
1Gi |
250m |
1000m |
| Heavy Processing |
1Gi |
2Gi |
500m |
2000m |
Full K8s manifests (Deployment, Service, HPA, ConfigMap, NetworkPolicy) → references/kubernetes.md.
CI/CD Pipeline Quick Reference
Stages: build & test → security scan → Docker build + Trivy scan → deploy staging → deploy production. Full YAML, strategies → references/cicd.md.
Graceful Shutdown Checklist
server.shutdown: graceful
spring.lifecycle.timeout-per-shutdown-phase: 30s
terminationGracePeriodSeconds: 45 (must be > shutdown timeout)
- Readiness probe fails first → K8s stops new traffic
- In-flight requests drain within timeout
- Kafka consumers commit offsets, DB pool drains
Related Skills
- observability-patterns — Prometheus metrics, structured logging, tracing
- spring-webflux-patterns — Spring Boot configuration, profiles
- architecture — Hexagonal structure mapping to Docker layers
1---2name: deployment-patterns3description: Deployment patterns for Java Spring Boot — Docker, Kubernetes, CI/CD, health probes, graceful shutdown. Use when writing Dockerfiles, K8s manifests (Deployment/Service/HPA/ConfigMap), CI/CD pipelines (GitHub Actions, GitLab CI), configuring health probes (liveness/readiness/startup), setting up graceful shutdown, sizing container resources, or containerizing Spring Boot applications.4---56# Deployment Patterns — Docker, K8s, CI/CD78## Quick Decision Matrix910| Need | Reference | When to read |11|------|-----------|-------------|12| Dockerfile | `references/dockerfile.md` | Creating/reviewing Docker images |13| K8s manifests | `references/kubernetes.md` | Writing Deployment, Service, HPA, ConfigMap |14| CI/CD pipeline | `references/cicd.md` | Setting up GitHub Actions or GitLab CI |15| Health probes | `references/health-probes.md` | Configuring liveness/readiness/startup probes |16| Generate Dockerfile | `scripts/generate-dockerfile.sh` | Scaffold a production Dockerfile |1718## Core Principles19201. **Separate build/runtime** — multi-stage builds (JDK build, JRE runtime)212. **Never root** — `USER appuser` in production images223. **Container-aware JVM** — `-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0`234. **Probe semantics** — liveness = internal only, readiness = external deps245. **Graceful shutdown** — `terminationGracePeriodSeconds` > `timeout-per-shutdown-phase`256. **No secrets in images** — K8s Secrets, SealedSecrets, or Vault2627## Dockerfile Essentials2829```dockerfile30# Build31FROM eclipse-temurin:17-jdk-jammy AS builder32WORKDIR /app33COPY gradle/ gradle/34COPY gradlew build.gradle.kts settings.gradle.kts ./35RUN ./gradlew dependencies --no-daemon || true36COPY src/ src/37RUN ./gradlew bootJar --no-daemon -x test3839# Runtime40FROM eclipse-temurin:17-jre-jammy41RUN groupadd -r appuser && useradd -r -g appuser appuser42WORKDIR /app43COPY --from=builder /app/build/libs/*.jar app.jar44USER appuser45ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=50.0"46EXPOSE 808047ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]48```4950Layered JAR, Maven, JVM flags → `references/dockerfile.md`.5152## Health Probes Summary5354```yaml55# application.yml56management:57 endpoint.health:58 probes.enabled: true59 group:60 liveness:61 include: livenessState62 readiness:63 include: readinessState, db, redis64server:65 shutdown: graceful66spring:67 lifecycle:68 timeout-per-shutdown-phase: 30s69```7071| Probe | Endpoint | Checks | Failure → |72|-------|----------|--------|-----------|73| Liveness | `/actuator/health/liveness` | App alive | Pod restart |74| Readiness | `/actuator/health/readiness` | DB, Redis | Remove from Service |75| Startup | `/actuator/health/liveness` | Init done | Wait |7677Custom HealthIndicators, composite readiness, shutdown sequence → `references/health-probes.md`.7879## Resource Sizing8081| Type | Mem Request | Mem Limit | CPU Request | CPU Limit |82|------|-----------|-----------|------------|----------|83| Lightweight API | 256Mi | 512Mi | 100m | 500m |84| Standard API | 512Mi | 1Gi | 250m | 1000m |85| Heavy Processing | 1Gi | 2Gi | 500m | 2000m |8687Full K8s manifests (Deployment, Service, HPA, ConfigMap, NetworkPolicy) → `references/kubernetes.md`.8889## CI/CD Pipeline Quick Reference9091Stages: build & test → security scan → Docker build + Trivy scan → deploy staging → deploy production. Full YAML, strategies → `references/cicd.md`.9293## Graceful Shutdown Checklist94951. `server.shutdown: graceful`962. `spring.lifecycle.timeout-per-shutdown-phase: 30s`973. `terminationGracePeriodSeconds: 45` (must be > shutdown timeout)984. Readiness probe fails first → K8s stops new traffic995. In-flight requests drain within timeout1006. Kafka consumers commit offsets, DB pool drains101102## Related Skills103104- **observability-patterns** — Prometheus metrics, structured logging, tracing105- **spring-webflux-patterns** — Spring Boot configuration, profiles106- **architecture** — Hexagonal structure mapping to Docker layers