Docker与Kubernetes部署Java应用容器化实践指南

 更新时间:2026年05月11日 09:21:13   作者:程序员鸭梨  
容器化是一种将应用程序及其依赖打包成一个可移植的单元的方法,容器能够在任何环境中运行,并且具有隔离性、可扩展性和高效性,这篇文章主要介绍了Docker与Kubernetes部署Java应用容器化实践指南的相关资料

今天我们来聊聊 Docker 与 Kubernetes 部署 Java 应用的最佳实践,这是容器化实践的重要技术。

一、容器化概述

容器化是一种将应用及其依赖打包为容器的技术,它提供了环境一致性、快速部署和资源隔离等优势。Docker 是目前最流行的容器化平台,而 Kubernetes 则是最流行的容器编排平台。

核心优势

  • 环境一致性:容器在不同环境中运行一致
  • 快速部署:容器启动速度快,部署时间短
  • 资源隔离:容器之间相互隔离,避免干扰
  • 资源利用率:容器占用资源少,提高服务器利用率
  • 易于扩展:支持水平扩展,适应不同负载

二、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. 优化 Dockerfile

# 使用最小基础镜像
FROM eclipse-temurin:25-jre-alpine

# 设置时区
ENV TZ=Asia/Shanghai
RUN apk add --no-cache tzdata && ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 创建非 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

# 查看容器状态
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

# 查看服务状态
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

五、监控与日志

1. 监控

# 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 微服务部署

场景描述

部署一个包含用户服务、订单服务、产品服务的 Java 微服务架构到 Kubernetes。

实现方案

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

产品服务

# 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 网关

# 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. 部署步骤

  1. 构建镜像:为每个服务构建 Docker 镜像
  2. 推送镜像:将镜像推送到 Docker 仓库
  3. 部署服务:使用 kubectl 部署所有服务
  4. 验证部署:检查服务状态和日志
  5. 配置监控:设置 Prometheus 和 Grafana 监控

七、最佳实践总结

1. Docker 最佳实践

  • 使用多阶段构建:减小镜像大小
  • 优化基础镜像:使用最小基础镜像
  • 非 root 用户:使用非 root 用户运行容器
  • 环境变量:使用环境变量配置应用
  • 健康检查:添加健康检查端点
  • 日志管理:使用标准输出和标准错误

2. Kubernetes 最佳实践

  • 资源限制:为每个容器设置资源限制
  • 健康检查:配置就绪探针和存活探针
  • 水平伸缩:使用 HPA 实现自动伸缩
  • 配置管理:使用 ConfigMap 管理配置
  • 密钥管理:使用 Secret 管理敏感数据
  • 持久化存储:使用 PVC 管理持久化数据
  • 服务发现:使用 Kubernetes 服务实现服务发现

3. CI/CD 最佳实践

  • 自动化构建:使用 Jenkins 或 GitHub Actions 自动化构建
  • 自动化测试:在构建过程中运行测试
  • 自动化部署:自动部署到测试和生产环境
  • 版本管理:使用语义化版本控制
  • 回滚机制:在部署失败时能够回滚

4. 监控与日志

  • 应用监控:使用 Prometheus 监控应用指标
  • 系统监控:监控 Kubernetes 集群状态
  • 日志聚合:使用 ELK 或 Loki 聚合日志
  • 告警机制:设置合理的告警规则
  • 仪表盘:使用 Grafana 创建监控仪表盘

八、总结与建议

Docker 与 Kubernetes 部署 Java 应用是现代应用部署的重要方式。通过合理使用容器化技术,我们可以:

  1. 提高部署效率:快速部署和扩展应用
  2. 增强系统可靠性:通过健康检查和自动伸缩提高系统可用性
  3. 改善资源利用率:容器占用资源少,提高服务器利用率
  4. 简化环境管理:容器在不同环境中运行一致
  5. 提高开发效率:开发环境与生产环境一致,减少环境问题

这其实可以更优雅一点,通过合理使用 Docker 和 Kubernetes,我们可以构建出更现代化、更可靠的 Java 应用部署方案。

到此这篇关于Docker与Kubernetes部署Java应用容器化实践指南的文章就介绍到这了,更多相关Docker与K8s部署Java应用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • RabbitMQ工作队列模式的使用解析

    RabbitMQ工作队列模式的使用解析

    文章介绍了RabbitMQ工作队列模式,通过多消费者竞争消费消息实现负载均衡,对比简单模式突出其分布式处理优势,详解轮询与公平分发策略,并提供环境配置、生产消费代码示例及运行分析,最后强调消息确认、持久化和动态扩容等使用技巧
    2025-08-08
  • springboot-2.3.x最新版源码阅读环境搭建(基于gradle构建)

    springboot-2.3.x最新版源码阅读环境搭建(基于gradle构建)

    这篇文章主要介绍了springboot-2.3.x最新版源码阅读环境搭建(基于gradle构建),需要的朋友可以参考下
    2020-08-08
  • Java代码实现从HTML文件中提取纯文本内容

    Java代码实现从HTML文件中提取纯文本内容

    在 Java 数据处理、文本清洗、内容解析等开发场景中,从 HTML 文件中剔除标签、样式、脚本等冗余格式,提取核心纯文本是高频需求,下面我们就来看看如何使用Java实现从HTML文件中提取纯文本内容吧
    2026-04-04
  • Java算法中的归并排序算法代码实现

    Java算法中的归并排序算法代码实现

    这篇文章主要介绍了Java算法中的归并排序算法代码实现,归并排序使用的是分治思想(Divide and Conquer),分治,顾名思义,就是分而治之,是将一个大问题分解成小的子问题来解决,需要的朋友可以参考下
    2023-12-12
  • 配置java.library.path加载库文件问题

    配置java.library.path加载库文件问题

    这篇文章主要介绍了配置java.library.path加载库文件问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • 解决idea中java出现无效的源发行版问题

    解决idea中java出现无效的源发行版问题

    这篇文章主要给大家介绍了关于解决idea中java出现无效的源发行版问题的相关资料,无效的源发行版是指IntelliJ IDEA无法正确识别和处理的源代码版本,这可能是由于错误的配置、缺少依赖项、不兼容的插件或其他问题导致的,需要的朋友可以参考下
    2024-01-01
  • Spring Boot 2.x 实现文件上传功能

    Spring Boot 2.x 实现文件上传功能

    这篇文章主要介绍了Spring Boot 2.x 实现文件上传功能,本文分步骤通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • java调用process线程阻塞问题的解决

    java调用process线程阻塞问题的解决

    这篇文章主要介绍了java调用process线程阻塞问题的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • java安全 ysoserial CommonsCollections1示例解析

    java安全 ysoserial CommonsCollections1示例解析

    这篇文章主要介绍了java安全 ysoserial CommonsCollections1示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • SpringBoot Tomcat漏洞修复的解决方法

    SpringBoot Tomcat漏洞修复的解决方法

    本文主要介绍了SpringBoot Tomcat漏洞修复的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-04-04

最新评论