Docker與Kubernetes部署Java應用容器化實踐指南
今天我們來聊聊 Docker 與 Kubernetes 部署 Java 應用的最佳實踐,這是容器化實踐的重要技術。
一、容器化概述
容器化是一種將應用及其依賴打包為容器的技術,它提供了環(huán)境一致性、快速部署和資源隔離等優(yōu)勢。Docker 是目前最流行的容器化平臺,而 Kubernetes 則是最流行的容器編排平臺。
核心優(yōu)勢
- 環(huán)境一致性:容器在不同環(huán)境中運行一致
- 快速部署:容器啟動速度快,部署時間短
- 資源隔離:容器之間相互隔離,避免干擾
- 資源利用率:容器占用資源少,提高服務器利用率
- 易于擴展:支持水平擴展,適應不同負載
二、Docker 容器化實踐
1. Dockerfile 編寫
# 基礎鏡像 FROM eclipse-temurin:25-jdk-alpine # 設置工作目錄 WORKDIR /app # 復制依賴文件 COPY pom.xml ./ # 下載依賴 RUN mvn dependency:go-offline # 復制源代碼 COPY src ./src # 構建應用 RUN mvn package -DskipTests # 暴露端口 EXPOSE 8080 # 運行應用 CMD ["java", "-jar", "target/app.jar"]
2. 多階段構建
# 構建階段 FROM eclipse-temurin:25-jdk-alpine AS build WORKDIR /app COPY pom.xml ./ RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests # 運行階段 FROM eclipse-temurin:25-jre-alpine WORKDIR /app COPY --from=build /app/target/app.jar ./ EXPOSE 8080 CMD ["java", "-jar", "app.jar"]
3. 優(yōu)化 Dockerfile
# 使用最小基礎鏡像 FROM eclipse-temurin:25-jre-alpine # 設置時區(qū) ENV TZ=Asia/Shanghai RUN apk add --no-cache tzdata && ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # 創(chuàng)建非 root 用戶 RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser # 設置工作目錄 WORKDIR /app # 復制應用 COPY target/app.jar ./ # 暴露端口 EXPOSE 8080 # 運行應用 CMD ["java", "-jar", "app.jar"]
4. 構建和運行
# 構建鏡像 docker build -t my-java-app:latest . # 運行容器 docker run -d -p 8080:8080 --name my-app my-java-app:latest # 查看容器狀態(tài) docker ps # 查看容器日志 docker logs my-app # 進入容器 docker exec -it my-app /bin/sh
5. Docker Compose
# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_HOST=db
- DB_PORT=5432
- DB_NAME=mydb
- DB_USER=user
- DB_PASSWORD=password
depends_on:
- db
db:
image: postgres:13
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
# 啟動服務 docker-compose up -d # 停止服務 docker-compose down # 查看服務狀態(tài) docker-compose ps
三、Kubernetes 部署實踐
1. 部署配置
# deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-java-app
spec:
replicas: 3
selector:
matchLabels:
app: my-java-app
template:
metadata:
labels:
app: my-java-app
spec:
containers:
- name: my-java-app
image: my-java-app:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: DB_HOST
value: "db-service"
- name: DB_PORT
value: "5432"
- name: DB_NAME
value: "mydb"
- name: DB_USER
value: "user"
- name: DB_PASSWORD
value: "password"
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
2. 服務配置
# service.yml
apiVersion: v1
kind: Service
metadata:
name: my-java-app-service
spec:
selector:
app: my-java-app
ports:
- port: 8080
targetPort: 8080
type: LoadBalancer
3. 配置管理
# configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-java-app-config
data:
application.yml: |
spring:
profiles:
active: prod
datasource:
url: jdbc:postgresql://db-service:5432/mydb
username: user
password: password
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
format_sql: true
# deployment.yml (with configmap)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-java-app
spec:
replicas: 3
selector:
matchLabels:
app: my-java-app
template:
metadata:
labels:
app: my-java-app
spec:
containers:
- name: my-java-app
image: my-java-app:latest
ports:
- containerPort: 8080
volumeMounts:
- name: config-volume
mountPath: /app/config
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
volumes:
- name: config-volume
configMap:
name: my-java-app-config
4. 密鑰管理
# secret.yml apiVersion: v1 kind: Secret metadata: name: my-java-app-secret type: Opaque data: db-password: dXNlci1wYXNzd29yZA== # base64 encoded jwt-secret: c29tZS1qd3Qtc2VjcmV0
# deployment.yml (with secret)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-java-app
spec:
replicas: 3
selector:
matchLabels:
app: my-java-app
template:
metadata:
labels:
app: my-java-app
spec:
containers:
- name: my-java-app
image: my-java-app:latest
ports:
- containerPort: 8080
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-java-app-secret
key: db-password
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: my-java-app-secret
key: jwt-secret
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
5. 持久化存儲
# persistentvolumeclaim.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-java-app-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard
# deployment.yml (with pvc)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-java-app
spec:
replicas: 3
selector:
matchLabels:
app: my-java-app
template:
metadata:
labels:
app: my-java-app
spec:
containers:
- name: my-java-app
image: my-java-app:latest
ports:
- containerPort: 8080
volumeMounts:
- name: data-volume
mountPath: /app/data
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: my-java-app-pvc
6. 水平自動伸縮
# horizontalpodautoscaler.yml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-java-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-java-app
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
7. 健康檢查
# deployment.yml (with health checks)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-java-app
spec:
replicas: 3
selector:
matchLabels:
app: my-java-app
template:
metadata:
labels:
app: my-java-app
spec:
containers:
- name: my-java-app
image: my-java-app:latest
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 30
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
四、CI/CD 集成
1. Jenkins 流水線
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
stage('Build Docker Image') {
steps {
sh 'docker build -t my-java-app:${BUILD_NUMBER} .'
sh 'docker tag my-java-app:${BUILD_NUMBER} my-java-app:latest'
}
}
stage('Push to Registry') {
steps {
sh 'docker push my-java-app:${BUILD_NUMBER}'
sh 'docker push my-java-app:latest'
}
}
stage('Deploy to Kubernetes') {
steps {
sh 'kubectl apply -f k8s/deployment.yml'
sh 'kubectl apply -f k8s/service.yml'
sh 'kubectl rollout status deployment/my-java-app'
}
}
}
}
2. GitHub Actions
name: CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 25
uses: actions/setup-java@v2
with:
java-version: '25'
distribution: 'adopt'
- name: Build with Maven
run: mvn clean package -DskipTests
- name: Run tests
run: mvn test
- name: Build Docker image
run: docker build -t my-java-app:${{ github.sha }} .
- name: Push to Docker Hub
run: |
docker tag my-java-app:${{ github.sha }} my-java-app:latest
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker push my-java-app:${{ github.sha }}
docker push my-java-app:latest
- name: Deploy to Kubernetes
run: |
kubectl config use-context my-cluster
kubectl apply -f k8s/deployment.yml
kubectl apply -f k8s/service.yml
kubectl rollout status deployment/my-java-app
五、監(jiān)控與日志
1. 監(jiān)控
# prometheus.yml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: my-java-app-monitor
labels:
release: prometheus
spec:
selector:
matchLabels:
app: my-java-app
endpoints:
- port: 8080
path: /actuator/prometheus
interval: 15s
2. 日志
# deployment.yml (with logging)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-java-app
spec:
replicas: 3
selector:
matchLabels:
app: my-java-app
template:
metadata:
labels:
app: my-java-app
spec:
containers:
- name: my-java-app
image: my-java-app:latest
ports:
- containerPort: 8080
env:
- name: LOGGING_LEVEL_ROOT
value: "info"
- name: LOGGING_LEVEL_COM_EXAMPLE
value: "debug"
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
六、實踐案例:Java 微服務部署
場景描述
部署一個包含用戶服務、訂單服務、產(chǎn)品服務的 Java 微服務架構到 Kubernetes。
實現(xiàn)方案
1. 服務配置
用戶服務
# user-service-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: EUREKA_CLIENT_SERVICEURL_DEFAULTZONE
value: "http://eureka-service:8761/eureka/"
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- port: 8080
targetPort: 8080
type: ClusterIP
訂單服務
# order-service-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: order-service:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: EUREKA_CLIENT_SERVICEURL_DEFAULTZONE
value: "http://eureka-service:8761/eureka/"
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector:
app: order-service
ports:
- port: 8080
targetPort: 8080
type: ClusterIP
產(chǎn)品服務
# product-service-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-service
spec:
replicas: 3
selector:
matchLabels:
app: product-service
template:
metadata:
labels:
app: product-service
spec:
containers:
- name: product-service
image: product-service:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: EUREKA_CLIENT_SERVICEURL_DEFAULTZONE
value: "http://eureka-service:8761/eureka/"
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: product-service
spec:
selector:
app: product-service
ports:
- port: 8080
targetPort: 8080
type: ClusterIP
Eureka 服務
# eureka-service-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: eureka-service
spec:
replicas: 1
selector:
matchLabels:
app: eureka-service
template:
metadata:
labels:
app: eureka-service
spec:
containers:
- name: eureka-service
image: eureka-service:latest
ports:
- containerPort: 8761
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: eureka-service
spec:
selector:
app: eureka-service
ports:
- port: 8761
targetPort: 8761
type: ClusterIP
API 網(wǎng)關
# gateway-service-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway-service
spec:
replicas: 3
selector:
matchLabels:
app: gateway-service
template:
metadata:
labels:
app: gateway-service
spec:
containers:
- name: gateway-service
image: gateway-service:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: EUREKA_CLIENT_SERVICEURL_DEFAULTZONE
value: "http://eureka-service:8761/eureka/"
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: gateway-service
spec:
selector:
app: gateway-service
ports:
- port: 8080
targetPort: 8080
type: LoadBalancer
2. 部署步驟
- 構建鏡像:為每個服務構建 Docker 鏡像
- 推送鏡像:將鏡像推送到 Docker 倉庫
- 部署服務:使用 kubectl 部署所有服務
- 驗證部署:檢查服務狀態(tài)和日志
- 配置監(jiān)控:設置 Prometheus 和 Grafana 監(jiān)控
七、最佳實踐總結
1. Docker 最佳實踐
- 使用多階段構建:減小鏡像大小
- 優(yōu)化基礎鏡像:使用最小基礎鏡像
- 非 root 用戶:使用非 root 用戶運行容器
- 環(huán)境變量:使用環(huán)境變量配置應用
- 健康檢查:添加健康檢查端點
- 日志管理:使用標準輸出和標準錯誤
2. Kubernetes 最佳實踐
- 資源限制:為每個容器設置資源限制
- 健康檢查:配置就緒探針和存活探針
- 水平伸縮:使用 HPA 實現(xiàn)自動伸縮
- 配置管理:使用 ConfigMap 管理配置
- 密鑰管理:使用 Secret 管理敏感數(shù)據(jù)
- 持久化存儲:使用 PVC 管理持久化數(shù)據(jù)
- 服務發(fā)現(xiàn):使用 Kubernetes 服務實現(xiàn)服務發(fā)現(xiàn)
3. CI/CD 最佳實踐
- 自動化構建:使用 Jenkins 或 GitHub Actions 自動化構建
- 自動化測試:在構建過程中運行測試
- 自動化部署:自動部署到測試和生產(chǎn)環(huán)境
- 版本管理:使用語義化版本控制
- 回滾機制:在部署失敗時能夠回滾
4. 監(jiān)控與日志
- 應用監(jiān)控:使用 Prometheus 監(jiān)控應用指標
- 系統(tǒng)監(jiān)控:監(jiān)控 Kubernetes 集群狀態(tài)
- 日志聚合:使用 ELK 或 Loki 聚合日志
- 告警機制:設置合理的告警規(guī)則
- 儀表盤:使用 Grafana 創(chuàng)建監(jiān)控儀表盤
八、總結與建議
Docker 與 Kubernetes 部署 Java 應用是現(xiàn)代應用部署的重要方式。通過合理使用容器化技術,我們可以:
- 提高部署效率:快速部署和擴展應用
- 增強系統(tǒng)可靠性:通過健康檢查和自動伸縮提高系統(tǒng)可用性
- 改善資源利用率:容器占用資源少,提高服務器利用率
- 簡化環(huán)境管理:容器在不同環(huán)境中運行一致
- 提高開發(fā)效率:開發(fā)環(huán)境與生產(chǎn)環(huán)境一致,減少環(huán)境問題
這其實可以更優(yōu)雅一點,通過合理使用 Docker 和 Kubernetes,我們可以構建出更現(xiàn)代化、更可靠的 Java 應用部署方案。
到此這篇關于Docker與Kubernetes部署Java應用容器化實踐指南的文章就介紹到這了,更多相關Docker與K8s部署Java應用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構建)
這篇文章主要介紹了springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構建),需要的朋友可以參考下2020-08-08
Java代碼實現(xiàn)從HTML文件中提取純文本內(nèi)容
在?Java?數(shù)據(jù)處理、文本清洗、內(nèi)容解析等開發(fā)場景中,從?HTML?文件中剔除標簽、樣式、腳本等冗余格式,提取核心純文本是高頻需求,下面我們就來看看如何使用Java實現(xiàn)從HTML文件中提取純文本內(nèi)容吧2026-04-04
解決idea中java出現(xiàn)無效的源發(fā)行版問題
這篇文章主要給大家介紹了關于解決idea中java出現(xiàn)無效的源發(fā)行版問題的相關資料,無效的源發(fā)行版是指IntelliJ IDEA無法正確識別和處理的源代碼版本,這可能是由于錯誤的配置、缺少依賴項、不兼容的插件或其他問題導致的,需要的朋友可以參考下2024-01-01
Spring Boot 2.x 實現(xiàn)文件上傳功能
這篇文章主要介紹了Spring Boot 2.x 實現(xiàn)文件上傳功能,本文分步驟通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
java安全?ysoserial?CommonsCollections1示例解析
這篇文章主要介紹了java安全?ysoserial?CommonsCollections1示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10

