Docker與Kubernetes部署Java應(yīng)用容器化實(shí)踐指南
今天我們來(lái)聊聊 Docker 與 Kubernetes 部署 Java 應(yīng)用的最佳實(shí)踐,這是容器化實(shí)踐的重要技術(shù)。
一、容器化概述
容器化是一種將應(yīng)用及其依賴打包為容器的技術(shù),它提供了環(huán)境一致性、快速部署和資源隔離等優(yōu)勢(shì)。Docker 是目前最流行的容器化平臺(tái),而 Kubernetes 則是最流行的容器編排平臺(tái)。
核心優(yōu)勢(shì)
- 環(huán)境一致性:容器在不同環(huán)境中運(yùn)行一致
- 快速部署:容器啟動(dòng)速度快,部署時(shí)間短
- 資源隔離:容器之間相互隔離,避免干擾
- 資源利用率:容器占用資源少,提高服務(wù)器利用率
- 易于擴(kuò)展:支持水平擴(kuò)展,適應(yīng)不同負(fù)載
二、Docker 容器化實(shí)踐
1. Dockerfile 編寫(xiě)
# 基礎(chǔ)鏡像 FROM eclipse-temurin:25-jdk-alpine # 設(shè)置工作目錄 WORKDIR /app # 復(fù)制依賴文件 COPY pom.xml ./ # 下載依賴 RUN mvn dependency:go-offline # 復(fù)制源代碼 COPY src ./src # 構(gòu)建應(yīng)用 RUN mvn package -DskipTests # 暴露端口 EXPOSE 8080 # 運(yùn)行應(yīng)用 CMD ["java", "-jar", "target/app.jar"]
2. 多階段構(gòu)建
# 構(gòu)建階段 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 # 運(yùn)行階段 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
# 使用最小基礎(chǔ)鏡像 FROM eclipse-temurin:25-jre-alpine # 設(shè)置時(shí)區(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 # 設(shè)置工作目錄 WORKDIR /app # 復(fù)制應(yīng)用 COPY target/app.jar ./ # 暴露端口 EXPOSE 8080 # 運(yùn)行應(yīng)用 CMD ["java", "-jar", "app.jar"]
4. 構(gòu)建和運(yùn)行
# 構(gòu)建鏡像 docker build -t my-java-app:latest . # 運(yùn)行容器 docker run -d -p 8080:8080 --name my-app my-java-app:latest # 查看容器狀態(tài) docker ps # 查看容器日志 docker logs my-app # 進(jìn)入容器 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:
# 啟動(dòng)服務(wù) docker-compose up -d # 停止服務(wù) docker-compose down # 查看服務(wù)狀態(tài) docker-compose ps
三、Kubernetes 部署實(shí)踐
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. 服務(wù)配置
# 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. 持久化存儲(chǔ)
# 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. 水平自動(dòng)伸縮
# 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"
六、實(shí)踐案例:Java 微服務(wù)部署
場(chǎng)景描述
部署一個(gè)包含用戶服務(wù)、訂單服務(wù)、產(chǎn)品服務(wù)的 Java 微服務(wù)架構(gòu)到 Kubernetes。
實(shí)現(xiàn)方案
1. 服務(wù)配置
用戶服務(wù)
# 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
訂單服務(wù)
# 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)品服務(wù)
# 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 服務(wù)
# 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)關(guān)
# 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. 部署步驟
- 構(gòu)建鏡像:為每個(gè)服務(wù)構(gòu)建 Docker 鏡像
- 推送鏡像:將鏡像推送到 Docker 倉(cāng)庫(kù)
- 部署服務(wù):使用 kubectl 部署所有服務(wù)
- 驗(yàn)證部署:檢查服務(wù)狀態(tài)和日志
- 配置監(jiān)控:設(shè)置 Prometheus 和 Grafana 監(jiān)控
七、最佳實(shí)踐總結(jié)
1. Docker 最佳實(shí)踐
- 使用多階段構(gòu)建:減小鏡像大小
- 優(yōu)化基礎(chǔ)鏡像:使用最小基礎(chǔ)鏡像
- 非 root 用戶:使用非 root 用戶運(yùn)行容器
- 環(huán)境變量:使用環(huán)境變量配置應(yīng)用
- 健康檢查:添加健康檢查端點(diǎn)
- 日志管理:使用標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤
2. Kubernetes 最佳實(shí)踐
- 資源限制:為每個(gè)容器設(shè)置資源限制
- 健康檢查:配置就緒探針和存活探針
- 水平伸縮:使用 HPA 實(shí)現(xiàn)自動(dòng)伸縮
- 配置管理:使用 ConfigMap 管理配置
- 密鑰管理:使用 Secret 管理敏感數(shù)據(jù)
- 持久化存儲(chǔ):使用 PVC 管理持久化數(shù)據(jù)
- 服務(wù)發(fā)現(xiàn):使用 Kubernetes 服務(wù)實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)
3. CI/CD 最佳實(shí)踐
- 自動(dòng)化構(gòu)建:使用 Jenkins 或 GitHub Actions 自動(dòng)化構(gòu)建
- 自動(dòng)化測(cè)試:在構(gòu)建過(guò)程中運(yùn)行測(cè)試
- 自動(dòng)化部署:自動(dòng)部署到測(cè)試和生產(chǎn)環(huán)境
- 版本管理:使用語(yǔ)義化版本控制
- 回滾機(jī)制:在部署失敗時(shí)能夠回滾
4. 監(jiān)控與日志
- 應(yīng)用監(jiān)控:使用 Prometheus 監(jiān)控應(yīng)用指標(biāo)
- 系統(tǒng)監(jiān)控:監(jiān)控 Kubernetes 集群狀態(tài)
- 日志聚合:使用 ELK 或 Loki 聚合日志
- 告警機(jī)制:設(shè)置合理的告警規(guī)則
- 儀表盤:使用 Grafana 創(chuàng)建監(jiān)控儀表盤
八、總結(jié)與建議
Docker 與 Kubernetes 部署 Java 應(yīng)用是現(xiàn)代應(yīng)用部署的重要方式。通過(guò)合理使用容器化技術(shù),我們可以:
- 提高部署效率:快速部署和擴(kuò)展應(yīng)用
- 增強(qiáng)系統(tǒng)可靠性:通過(guò)健康檢查和自動(dòng)伸縮提高系統(tǒng)可用性
- 改善資源利用率:容器占用資源少,提高服務(wù)器利用率
- 簡(jiǎn)化環(huán)境管理:容器在不同環(huán)境中運(yùn)行一致
- 提高開(kāi)發(fā)效率:開(kāi)發(fā)環(huán)境與生產(chǎn)環(huán)境一致,減少環(huán)境問(wèn)題
這其實(shí)可以更優(yōu)雅一點(diǎn),通過(guò)合理使用 Docker 和 Kubernetes,我們可以構(gòu)建出更現(xiàn)代化、更可靠的 Java 應(yīng)用部署方案。
到此這篇關(guān)于Docker與Kubernetes部署Java應(yīng)用容器化實(shí)踐指南的文章就介紹到這了,更多相關(guān)Docker與K8s部署Java應(yīng)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構(gòu)建)
這篇文章主要介紹了springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構(gòu)建),需要的朋友可以參考下2020-08-08
Java代碼實(shí)現(xiàn)從HTML文件中提取純文本內(nèi)容
在?Java?數(shù)據(jù)處理、文本清洗、內(nèi)容解析等開(kāi)發(fā)場(chǎng)景中,從?HTML?文件中剔除標(biāo)簽、樣式、腳本等冗余格式,提取核心純文本是高頻需求,下面我們就來(lái)看看如何使用Java實(shí)現(xiàn)從HTML文件中提取純文本內(nèi)容吧2026-04-04
配置java.library.path加載庫(kù)文件問(wèn)題
這篇文章主要介紹了配置java.library.path加載庫(kù)文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
解決idea中java出現(xiàn)無(wú)效的源發(fā)行版問(wèn)題
這篇文章主要給大家介紹了關(guān)于解決idea中java出現(xiàn)無(wú)效的源發(fā)行版問(wèn)題的相關(guān)資料,無(wú)效的源發(fā)行版是指IntelliJ IDEA無(wú)法正確識(shí)別和處理的源代碼版本,這可能是由于錯(cuò)誤的配置、缺少依賴項(xiàng)、不兼容的插件或其他問(wèn)題導(dǎo)致的,需要的朋友可以參考下2024-01-01
Spring Boot 2.x 實(shí)現(xiàn)文件上傳功能
這篇文章主要介紹了Spring Boot 2.x 實(shí)現(xiàn)文件上傳功能,本文分步驟通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
java調(diào)用process線程阻塞問(wèn)題的解決
這篇文章主要介紹了java調(diào)用process線程阻塞問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
java安全?ysoserial?CommonsCollections1示例解析
這篇文章主要介紹了java安全?ysoserial?CommonsCollections1示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
SpringBoot Tomcat漏洞修復(fù)的解決方法
本文主要介紹了SpringBoot Tomcat漏洞修復(fù)的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04

