Docker容器化深度实战:SpringCloud微服务镜像优化从1GB到100MB,附生产环境完整配置

3 阅读14分钟

第11天:Docker容器化 - 微服务住进"集装箱",一次构建处处运行🐳

一、先白话白话Docker为啥牛X

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

经典问题:"在我本地是好的!"

开发说:"我本地跑得好好的!" 测试说:"测试环境为啥报错?" 运维说:"生产环境又挂了!"

根本原因

  • 开发:Windows + JDK 11 + MySQL 8.0
  • 测试:Linux + JDK 8 + MySQL 5.7
  • 生产:Linux + JDK 17 + MySQL 8.0

环境不一致,问题百出!

Docker解决方案:"集装箱思维"

应用+依赖+环境打包成一个集装箱(镜像)

  • 开发:打好包
  • 测试:直接运行
  • 生产:直接运行

一次构建,处处运行!

二、Docker核心概念(5分钟搞懂)

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

1. 镜像(Image)📦

  • 模板:就像虚拟机镜像
  • 只读:不能修改,只能基于它创建新镜像
  • 分层存储:每层都可复用,节省空间

2. 容器(Container)🚢

  • 运行实例:镜像运行起来就是容器
  • 可写层:在镜像基础上加一层可写层
  • 隔离环境:有自己的文件系统、网络、进程

3. 仓库(Registry)🏢

  • 存放镜像的地方:Docker Hub、阿里云、私有仓库
  • 类似Git:可以push/pull镜像

4. Dockerfile📝

  • 构建脚本:告诉Docker怎么构建镜像
  • 指令集:FROM、RUN、COPY、CMD等

5. Docker Compose🚀

  • 多容器管理:一键启动所有服务
  • 定义服务依赖:数据库、Redis、应用服务

三、先安装Docker(5分钟搞定)

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

Windows/Mac:Docker Desktop

  1. 官网下载:www.docker.com/products/do…
  2. 一键安装,傻瓜式操作
  3. 启动后右下角看到🐳图标就OK

Linux:命令行安装

# 1. 卸载旧版本
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine

# 2. 安装依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

# 3. 设置仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 4. 安装Docker
sudo yum install docker-ce docker-ce-cli containerd.io

# 5. 启动Docker
sudo systemctl start docker
sudo systemctl enable docker

# 6. 验证安装
docker --version
docker run hello-world

配置镜像加速(国内必须!)

// Docker Desktop:Settings -> Docker Engine
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ],
  "insecure-registries": [],
  "debug": true,
  "experimental": false
}

四、把user-service做成镜像

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

步骤1:准备项目结构

user-service/
├── src/
├── target/
│   └── user-service-0.0.1-SNAPSHOT.jar
├── Dockerfile          # Docker构建文件
├── docker-entrypoint.sh  # 启动脚本
└── docker-compose.yml    # 多服务编排

步骤2:写Dockerfile(核心!)

# 第一阶段:构建
FROM maven:3.8.6-openjdk-17-slim AS builder

# 设置工作目录
WORKDIR /app

# 复制pom文件(利用缓存)
COPY pom.xml .

# 下载依赖(利用缓存,只要pom没变就不重复下载)
RUN mvn dependency:go-offline -B

# 复制源码
COPY src ./src

# 打包
RUN mvn clean package -DskipTests

# 第二阶段:运行
FROM openjdk:17-jdk-slim

# 时区设置(中文环境必须!)
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo 'Asia/Shanghai' > /etc/timezone

# 创建非root用户(安全!)
RUN groupadd -r spring && useradd -r -g spring spring
USER spring:spring

# 设置工作目录
WORKDIR /app

# 从构建阶段复制jar包
COPY --from=builder --chown=spring:spring /app/target/user-service-*.jar app.jar

# JVM参数优化
ENV JAVA_OPTS="-Xms512m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/heapdump.hprof"

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
    CMD curl -f http://localhost:8080/actuator/health || exit 1

# 暴露端口
EXPOSE 8080

# 启动命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.jar"]

步骤3:写启动脚本(可选但推荐)

#!/bin/bash
# docker-entrypoint.sh

set -e

# 等待依赖服务(比如数据库)
wait_for_host() {
    local host="$1"
    local port="$2"
    local max_attempts=30
    local attempt=1
    
    echo "等待 $host:$port 就绪..."
    
    while ! nc -z "$host" "$port"; do
        if [ $attempt -eq $max_attempts ]; then
            echo "$host:$port 没有响应,退出"
            exit 1
        fi
        
        echo "尝试 $attempt/$max_attempts: $host:$port 还未就绪,等待2秒..."
        sleep 2
        attempt=$((attempt + 1))
    done
    
    echo "$host:$port 已就绪"
}

# 等待MySQL
if [ -n "$DB_HOST" ] && [ -n "$DB_PORT" ]; then
    wait_for_host "$DB_HOST" "$DB_PORT"
fi

# 等待Redis
if [ -n "$REDIS_HOST" ] && [ -n "$REDIS_PORT" ]; then
    wait_for_host "$REDIS_HOST" "$REDIS_PORT"
fi

# 等待Nacos
if [ -n "$NACOS_HOST" ] && [ -n "$NACOS_PORT" ]; then
    wait_for_host "$NACOS_HOST" "$NACOS_PORT"
fi

# 执行Java命令
exec java $JAVA_OPTS -jar /app/app.jar "$@"

步骤4:构建镜像

# 进入项目目录
cd user-service

# 构建镜像(注意最后有个点)
docker build -t user-service:1.0.0 .

# 查看镜像
docker images | grep user-service
# 输出:user-service  1.0.0   abc123def456  2分钟前  245MB

# 运行容器测试
docker run -d \
  --name user-service \
  -p 8081:8080 \
  -e NACOS_HOST=host.docker.internal \
  -e NACOS_PORT=8848 \
  user-service:1.0.0

# 查看日志
docker logs -f user-service

# 查看容器状态
docker ps | grep user-service

五、Dockerfile高级技巧(镜像从1GB瘦身到100MB)

技巧1:多阶段构建(瘦身关键!)

# 第一阶段:构建(用完整JDK)
FROM maven:3.8.6-openjdk-17 AS builder
WORKDIR /app
COPY . .
RUN mvn clean package -DskipTests

# 第二阶段:运行(用最小JRE)
FROM openjdk:17-jre-slim  # 比JDK小100MB!
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar

# 进一步瘦身:用alpine版本
# FROM openjdk:17-jre-alpine  # 再小50MB!

技巧2:分层优化(利用缓存)

# 错误的顺序(每次代码变更都重新下载依赖)
COPY . .  # 这一行变了,下面所有缓存都失效
RUN mvn clean package

# 正确的顺序(利用缓存)
COPY pom.xml .  # 依赖很少变,优先复制
RUN mvn dependency:go-offline -B  # 下载依赖,这层被缓存

COPY src ./src  # 代码经常变,最后复制
RUN mvn clean package -DskipTests  # 这层经常变

技巧3:删除无用文件

# 清理Maven缓存
RUN mvn clean package -DskipTests && \
    rm -rf /root/.m2  # 删除Maven缓存,节省200MB!

# 或者用专门的清理层
RUN --mount=type=cache,target=/root/.m2 \
    mvn clean package -DskipTests

# 清理apt缓存(如果用了apt)
RUN apt-get update && \
    apt-get install -y curl && \
    rm -rf /var/lib/apt/lists/*  # 清理包管理器缓存

技巧4:使用.dockerignore(重要!)

# .dockerignore文件
.git
.gitignore
README.md
*.log
target/
*.iml
.idea/
*.jar
*.war
*.tar.gz
.DS_Store
**/node_modules
**/.gradle
**/build
**/.settings
**/.classpath
**/.project

技巧5:最终极瘦身方案

# 使用distroless镜像(Google出品,极简)
FROM gcr.io/distroless/java17-debian11

# 或者用jlink制作自定义JRE
FROM openjdk:17 AS jlink
RUN jlink \
    --add-modules java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \
    --strip-debug \
    --no-man-pages \
    --no-header-files \
    --compress=2 \
    --output /jre-minimal

FROM debian:bullseye-slim
COPY --from=jlink /jre-minimal /opt/jre
ENV JAVA_HOME=/opt/jre
ENV PATH="$JAVA_HOME/bin:$PATH"
COPY --from=builder /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

六、Docker Compose一键启动所有服务

docker-compose.yml

version: '3.8'

services:
  # Nacos服务注册中心
  nacos:
    image: nacos/nacos-server:v2.1.0
    container_name: nacos
    environment:
      - MODE=standalone  # 单机模式
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=mysql
      - MYSQL_SERVICE_PORT=3306
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=123456
      - MYSQL_SERVICE_DB_NAME=nacos
    ports:
      - "8848:8848"
      - "9848:9848"
    depends_on:
      mysql:
        condition: service_healthy
    networks:
      - microservice-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8848/nacos"]
      interval: 30s
      timeout: 10s
      retries: 3

  # MySQL数据库
  mysql:
    image: mysql:8.0
    container_name: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_DATABASE=nacos
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
      - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
    command: 
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --default-authentication-plugin=mysql_native_password
    networks:
      - microservice-network
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p123456"]
      interval: 10s
      timeout: 5s
      retries: 3

  # Redis缓存
  redis:
    image: redis:7-alpine
    container_name: redis
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    command: redis-server --appendonly yes --requirepass "redis123"
    networks:
      - microservice-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

  # 用户服务
  user-service:
    build: 
      context: ./user-service
      dockerfile: Dockerfile
      args:
        - APP_VERSION=1.0.0
    container_name: user-service
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - NACOS_SERVER_ADDR=nacos:8848
      - MYSQL_HOST=mysql
      - MYSQL_PORT=3306
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    ports:
      - "8081:8080"
    depends_on:
      nacos:
        condition: service_healthy
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - microservice-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M
    restart: unless-stopped  # 自动重启

  # 订单服务
  order-service:
    build: ./order-service
    container_name: order-service
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - NACOS_SERVER_ADDR=nacos:8848
      - USER_SERVICE_HOST=user-service
      - USER_SERVICE_PORT=8080
    ports:
      - "8082:8080"
    depends_on:
      - nacos
      - user-service
    networks:
      - microservice-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # 商品服务
  product-service:
    build: ./product-service
    container_name: product-service
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - NACOS_SERVER_ADDR=nacos:8848
    ports:
      - "8083:8080"
    depends_on:
      - nacos
      - mysql
    networks:
      - microservice-network

  # API网关
  api-gateway:
    build: ./api-gateway
    container_name: api-gateway
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - NACOS_SERVER_ADDR=nacos:8848
    ports:
      - "9000:9000"
    depends_on:
      - nacos
      - user-service
      - order-service
      - product-service
    networks:
      - microservice-network

  # Spring Boot Admin监控
  admin-server:
    build: ./admin-server
    container_name: admin-server
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - NACOS_SERVER_ADDR=nacos:8848
    ports:
      - "8888:8888"
    depends_on:
      - nacos
    networks:
      - microservice-network

  # Zipkin链路追踪
  zipkin:
    image: openzipkin/zipkin:latest
    container_name: zipkin
    ports:
      - "9411:9411"
    environment:
      - STORAGE_TYPE=mem
    networks:
      - microservice-network

  # 端口ainer管理工具
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    ports:
      - "9001:9000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer-data:/data
    networks:
      - microservice-network
    restart: unless-stopped

# 网络配置
networks:
  microservice-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

# 数据卷配置
volumes:
  mysql-data:
  redis-data:
  portainer-data:

环境变量配置文件

# docker-compose.env
# 通用配置
SPRING_PROFILES_ACTIVE=docker
NACOS_SERVER_ADDR=nacos:8848

# 数据库配置
MYSQL_HOST=mysql
MYSQL_PORT=3306
MYSQL_DATABASE=user_db
MYSQL_USERNAME=root
MYSQL_PASSWORD=123456

# Redis配置
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=redis123

# 服务配置
USER_SERVICE_HOST=user-service
USER_SERVICE_PORT=8080
ORDER_SERVICE_HOST=order-service
ORDER_SERVICE_PORT=8080
PRODUCT_SERVICE_HOST=product-service
PRODUCT_SERVICE_PORT=8080

# JVM参数
JAVA_OPTS=-Xms512m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError

启动命令

# 一键启动所有服务
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs -f user-service

# 查看所有日志
docker-compose logs -f

# 重启单个服务
docker-compose restart user-service

# 停止所有服务
docker-compose down

# 停止并删除数据卷
docker-compose down -v

# 重新构建镜像
docker-compose build --no-cache

# 水平扩展(启动3个user-service实例)
docker-compose up -d --scale user-service=3

七、生产环境最佳实践

1. 镜像安全扫描

# 使用Trivy扫描镜像漏洞
docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image user-service:1.0.0

# 使用Docker Scout(Docker官方)
docker scout quickview user-service:1.0.0

# 扫描结果输出到HTML报告
docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image \
  --format template \
  --template "@contrib/html.tpl" \
  -o report.html \
  user-service:1.0.0

2. 镜像签名和验证

# 启用Docker Content Trust
export DOCKER_CONTENT_TRUST=1

# 构建并推送签名镜像
docker build -t myregistry.com/user-service:1.0.0 .
docker push myregistry.com/user-service:1.0.0

# 拉取时验证签名
docker pull myregistry.com/user-service:1.0.0

3. 使用多阶段构建减少攻击面

# 生产环境Dockerfile
FROM --platform=$BUILDPLATFORM maven:3.8.6-eclipse-temurin-17 AS builder
WORKDIR /workspace
COPY . .
RUN mvn clean package -DskipTests -Pprod

FROM --platform=$TARGETPLATFORM eclipse-temurin:17-jre-alpine AS runtime

# 安全:使用非root用户
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring

# 安全:创建不可变目录
RUN mkdir -p /app && chown spring:spring /app
WORKDIR /app

# 从构建阶段复制
COPY --from=builder --chown=spring:spring /workspace/target/*.jar app.jar

# 安全:设置只读文件系统
RUN chmod -R 555 /app && \
    chmod 755 /app/app.jar

# 安全:设置资源限制
ENV JAVA_OPTS="-XX:MaxRAMPercentage=75.0 -XX:+UseContainerSupport"

# 安全:健康检查
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
    CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1

ENTRYPOINT ["java", "-jar", "app.jar"]

4. 镜像仓库管理

# 推送到私有仓库
docker tag user-service:1.0.0 registry.mycompany.com/microservices/user-service:1.0.0
docker push registry.mycompany.com/microservices/user-service:1.0.0

# 拉取特定版本
docker pull registry.mycompany.com/microservices/user-service:1.0.0

# 查看仓库中的镜像
curl -u username:password https://registry.mycompany.com/v2/microservices/user-service/tags/list

# 删除旧镜像(保留最近5个版本)
docker images --filter "reference=registry.mycompany.com/microservices/user-service" --format "{{.Tag}}" | \
  sort -V | \
  head -n -5 | \
  xargs -I {} docker rmi registry.mycompany.com/microservices/user-service:{}

5. 使用BuildKit加速构建

# 启用BuildKit
export DOCKER_BUILDKIT=1

# 使用缓存镜像
docker build \
  --cache-from registry.mycompany.com/microservices/user-service:latest \
  -t registry.mycompany.com/microservices/user-service:1.0.0 \
  -t registry.mycompany.com/microservices/user-service:latest \
  .

# 并行构建多阶段
docker build \
  --build-arg BUILDKIT_INLINE_CACHE=1 \
  --cache-from registry.mycompany.com/microservices/user-service:latest \
  -t user-service:1.0.0 \
  .

八、Docker监控和调试

1. 容器监控

# 查看容器资源使用
docker stats

# 查看容器详情
docker inspect user-service

# 查看容器日志
docker logs -f --tail 100 user-service

# 查看容器进程
docker top user-service

# 查看容器资源限制
docker container inspect user-service --format='{{.HostConfig.Memory}}'

# 性能分析
docker run --rm -it --pid=container:user-service --net=container:user-service --cap-add sys_ptrace alpine sh
# 在容器内执行:top, ps, netstat等

2. 进入容器调试

# 进入容器shell
docker exec -it user-service sh

# 在容器内查看Java进程
ps aux | grep java

# 查看Java堆内存
jmap -heap 1

# 生成堆转储
jmap -dump:live,format=b,file=/app/heapdump.hprof 1

# 查看GC情况
jstat -gc 1 1000 10

# 线程转储
jstack 1 > /app/threaddump.txt

# 退出容器
exit

3. 容器网络调试

# 查看容器网络
docker network ls
docker network inspect microservice-network

# 容器间网络测试
docker exec user-service ping order-service
docker exec user-service curl http://order-service:8080/actuator/health

# 查看端口映射
docker port user-service

# 查看容器IP
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' user-service

4. 使用Docker Compose调试

# 查看服务依赖图
docker-compose config --services

# 验证配置文件
docker-compose config

# 调试模式运行
docker-compose up --build --force-recreate --abort-on-container-exit

# 查看服务日志
docker-compose logs --tail=100 -f user-service order-service

# 执行命令
docker-compose exec user-service sh
docker-compose exec mysql mysql -uroot -p123456

# 查看资源使用
docker-compose top

九、常见问题解决方案

1. 镜像构建慢

# 使用国内镜像源
# 创建或修改~/.docker/daemon.json
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ]
}

# 使用构建缓存
docker build --cache-from user-service:latest -t user-service:1.0.0 .

# 使用多阶段构建,减少层数

2. 容器启动报错

# 查看详细错误
docker logs user-service --details

# 调试模式启动
docker run -it --rm user-service:1.0.0 sh
# 在容器内手动启动
java -jar app.jar

# 检查环境变量
docker exec user-service env

# 检查端口冲突
netstat -tulpn | grep 8081

3. 容器内存泄漏

# 限制容器内存
docker run -d --name user-service --memory=512m --memory-swap=1g user-service:1.0.0

# 监控内存使用
docker stats user-service

# 进入容器分析
docker exec -it user-service sh
jmap -histo:live 1 | head -20

4. 容器网络问题

# 检查网络连通性
docker exec user-service curl -v http://order-service:8080

# 查看DNS解析
docker exec user-service cat /etc/resolv.conf
docker exec user-service nslookup order-service

# 创建自定义网络
docker network create --driver=bridge --subnet=172.25.0.0/16 microservice-net
docker run --network=microservice-net user-service:1.0.0

5. 数据持久化问题

# 使用数据卷
docker volume create mysql-data
docker run -d --name mysql -v mysql-data:/var/lib/mysql mysql:8.0

# 查看数据卷
docker volume inspect mysql-data

# 备份数据卷
docker run --rm -v mysql-data:/source -v $(pwd):/backup alpine tar czf /backup/mysql-backup.tar.gz -C /source .

# 恢复数据卷
docker run --rm -v mysql-data:/target -v $(pwd):/backup alpine tar xzf /backup/mysql-backup.tar.gz -C /target

十、Docker在CI/CD中的使用

GitHub Actions示例

# .github/workflows/docker-build.yml
name: Docker Build and Push

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v2
    
    - name: Login to DockerHub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}
    
    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v4
      with:
        images: myorg/user-service
        tags: |
          type=ref,event=branch
          type=sha,prefix={{branch}}-
          type=semver,pattern={{version}}
    
    - name: Build and push
      uses: docker/build-push-action@v4
      with:
        context: ./user-service
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}
        cache-from: type=registry,ref=myorg/user-service:latest
        cache-to: type=inline

Jenkins Pipeline示例

// Jenkinsfile
pipeline {
    agent any
    
    environment {
        DOCKER_REGISTRY = 'registry.mycompany.com'
        IMAGE_NAME = 'microservices/user-service'
    }
    
    stages {
        stage('Build') {
            steps {
                script {
                    docker.build("${IMAGE_NAME}:${env.BUILD_ID}")
                }
            }
        }
        
        stage('Test') {
            steps {
                script {
                    docker.image("${IMAGE_NAME}:${env.BUILD_ID}").inside {
                        sh 'mvn test'
                    }
                }
            }
        }
        
        stage('Security Scan') {
            steps {
                script {
                    sh """
                    docker run --rm \
                      -v /var/run/docker.sock:/var/run/docker.sock \
                      aquasec/trivy image \
                      --exit-code 1 \
                      --severity HIGH,CRITICAL \
                      ${IMAGE_NAME}:${env.BUILD_ID}
                    """
                }
            }
        }
        
        stage('Push') {
            steps {
                script {
                    docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-credentials') {
                        docker.image("${IMAGE_NAME}:${env.BUILD_ID}").push()
                        docker.image("${IMAGE_NAME}:${env.BUILD_ID}").push('latest')
                    }
                }
            }
        }
        
        stage('Deploy') {
            steps {
                script {
                    sh """
                    docker-compose -f docker-compose.prod.yml pull
                    docker-compose -f docker-compose.prod.yml up -d
                    """
                }
            }
        }
    }
}

十一、今儿个总结

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

学会了啥?

  1. ✅ Docker核心概念:镜像、容器、仓库
  2. ✅ Dockerfile编写技巧和多阶段构建
  3. ✅ Docker Compose多服务编排
  4. ✅ 镜像优化:从1GB瘦身到100MB
  5. ✅ 生产环境最佳实践和安全
  6. ✅ 容器监控和调试技巧
  7. ✅ CI/CD集成

关键点

  1. 多阶段构建是瘦身关键
  2. .dockerignore能加速构建
  3. 非root用户运行更安全
  4. 健康检查保证服务可用性
  5. 数据卷实现持久化存储
  6. 网络隔离保证服务安全

十二、明儿个学啥?

明天咱学Kubernetes

  • Docker是集装箱,Kubernetes是集装箱货轮
  • 自动扩缩容:流量大了自动加机器
  • 自愈能力:容器挂了自动重启
  • 服务发现:自动发现和负载均衡
  • 配置管理:ConfigMap和Secret

明天咱从"手工部署"升级到"自动驾驶"!🚢


零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

Docker容器化深度实战:SpringCloud微服务镜像优化从1GB到100MB,附生产环境完整配置

【关注】 🔥 本文收录于《SpringCloud企业级实战》专栏,持续更新微服务架构系列
💡 关注+点赞,获取完整Dockerfile模板和docker-compose.yml配置
🚀 评论区留下你的Docker问题,24小时内必回
📚 配套GitHub项目:包含10+微服务Docker化完整示例
👨💻 下篇预告:Kubernetes实战,带你从Docker Compose平滑迁移到K8S

**