1. Docker镜像与容器基础操作精要

1.1 镜像的导入导出实战

在团队协作或离线环境中,镜像的导入导出是必备技能。使用 docker save docker load 命令可以实现镜像的持久化存储和迁移:

# 导出镜像为tar包
docker save -o my_springboot_app.tar myregistry/springboot-app:1.0

# 导入镜像
docker load -i my_springboot_app.tar

关键细节:导出时建议使用镜像ID而非标签,避免环境差异导致的标签冲突。通过 docker images --digests 查看镜像唯一标识。

镜像体积优化技巧:

  1. 多阶段构建:在Dockerfile中使用多个FROM指令,最终只保留运行时必要文件
  2. 层合并:合并RUN指令减少镜像层数(注意&&运算符的使用)
  3. 基础镜像选择:推荐使用alpine版本(如openjdk:8-jdk-alpine)

1.2 容器的持久化迁移

容器导出与镜像导出的本质区别在于容器包含运行时状态:

# 导出容器文件系统
docker export -o my_container.tar container_id

# 导入为镜像
docker import my_container.tar my_image:snapshot

典型应用场景:

  • 生产环境问题复现:将问题容器完整导出供开发团队分析
  • 状态备份:保存数据库容器的特定时间点状态
  • 离线部署:在内网环境中恢复完整服务栈

2. 容器网络互联进阶方案

2.1 默认网络模式对比

网络模式 隔离性 性能 适用场景
bridge(default) 中等 较好 单主机多容器通信
host 最佳 高性能网络应用
none 完全 无网络 特殊安全需求场景

2.2 用户自定义网络实践

创建自定义网络实现容器间安全通信:

docker network create --driver bridge --subnet 172.28.0.0/16 my_net
docker run -d --name app1 --network my_net springboot-app
docker run -d --name mysql --network my_net mysql:5.7

此时app1容器中可以直接通过 mysql 主机名访问数据库服务,DNS解析由Docker内置提供。

网络排错命令:

  • docker network inspect my_net 查看网络详情
  • docker exec -it app1 ping mysql 测试容器连通性
  • tcpdump -i eth0 -n 容器内抓包分析

2.3 跨主机容器通信方案

  1. Overlay网络 (适合Swarm集群):

    docker network create -d overlay my_overlay_net
    
  2. Macvlan (直接分配MAC地址):

    docker network create -d macvlan \
      --subnet=192.168.1.0/24 \
      --gateway=192.168.1.1 \
      -o parent=eth0 my_macvlan
    
  3. 第三方方案 :Weave、Flannel等CNI插件

3. SpringBoot微服务容器化全流程

3.1 项目结构优化建议

标准微服务项目应包含:

├── Dockerfile
├── docker-compose.yml
├── src
│   ├── main
│   │   ├── java
│   │   └── resources
│   └── test
├── config
│   ├── application.yml
│   └── application-prod.yml
└── scripts
    ├── entrypoint.sh
    └── healthcheck.sh

3.2 生产级Dockerfile示例

# 构建阶段
FROM maven:3.8.6-eclipse-temurin-17 as builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests

# 运行时阶段
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
COPY --from=builder /app/target/*.jar ./app.jar
COPY scripts/entrypoint.sh .
RUN chmod +x entrypoint.sh

# 安全加固
RUN useradd -ms /bin/bash appuser && \
    chown -R appuser:appuser /app
USER appuser

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

ENTRYPOINT ["./entrypoint.sh"]

关键优化点:

  1. 使用多阶段构建减小镜像体积(从~500MB降至~150MB)
  2. 非root用户运行增强安全性
  3. 健康检查对接SpringBoot Actuator
  4. 分离依赖下载与源码构建,利用Docker缓存

3.3 容器编排实战

docker-compose.yml示例:

version: '3.8'

services:
  app-service:
    build: .
    image: myorg/springboot-app:${TAG:-latest}
    networks:
      - backend
    depends_on:
      redis:
        condition: service_healthy
      mysql:
        condition: service_healthy
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 1G
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3

  mysql:
    image: mysql:5.7
    networks:
      - backend
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: app_db
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 10

  redis:
    image: redis:6-alpine
    networks:
      - backend
    command: redis-server --requirepass ${REDIS_PASSWORD}
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

volumes:
  mysql_data:

4. 生产环境问题排查手册

4.1 容器日志管理策略

  1. 日志驱动选择

    docker run --log-driver=json-file --log-opt max-size=10m --log-opt max-file=3 ...
    

    支持的类型包括:

    • json-file(默认)
    • syslog
    • journald
    • gelf(Graylog)
    • fluentd
  2. 日志查看技巧

    # 跟踪最新日志
    docker logs -f --tail 100 container_name
    
    # 按时间过滤
    docker logs --since 2023-01-01T00:00:00 container_name
    
    # 结合grep过滤
    docker logs container_name 2>&1 | grep "ERROR"
    

4.2 性能问题诊断

  1. 资源监控

    docker stats
    

    输出示例:

    CONTAINER ID   NAME        CPU %   MEM USAGE / LIMIT     MEM %   NET I/O       BLOCK I/O   PIDS
    a1b2c3d4e5f6   app-service 0.50%   512MiB / 1GiB         50.00%  1.2MB / 3MB   0B / 0B     15
    
  2. 深入分析工具

    • docker exec -it container_name top
    • docker run --pid=container:app-service --net=container:app-service busybox top
    • docker checkpoint 创建检查点供后续分析

4.3 常见问题速查表

问题现象 可能原因 解决方案
容器启动立即退出 1. 启动命令错误
2. 端口冲突
1. docker logs 查看错误
2. netstat -tulnp 检查端口占用
容器间网络不通 1. 不在同一网络
2. 防火墙
1. docker network inspect 检查网络配置
2. 检查iptables/nftables规则
磁盘空间不足 1. 日志堆积
2. 悬空镜像
1. 设置日志轮转
2. docker system prune 清理
SpringBoot应用启动慢 1. JVM参数不合理
2. 资源不足
1. 添加 -XX:+AlwaysPreTouch
2. 增加CPU/内存配额
数据库连接失败 1. 网络隔离
2. 认证失败
1. 检查容器网络
2. 验证环境变量配置

5. 微服务架构下的Docker实践

5.1 配置管理最佳实践

  1. 环境变量注入

    # docker-compose.yml
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - DB_URL=jdbc:mysql://mysql:3306/app_db
    
  2. 配置分离方案

    # Dockerfile
    VOLUME /app/config
    COPY config/application-prod.yml /app/config/
    

    启动时挂载:

    docker run -v ./config:/app/config springboot-app
    

5.2 服务发现与负载均衡

  1. DNS轮询

    # docker-compose.yml
    services:
      app-service:
        deploy:
          replicas: 3
    

    其他容器通过服务名访问时,Docker会自动负载均衡

  2. Nginx动态配置

    docker run -d --name nginx \
      -v /path/to/nginx.conf:/etc/nginx/nginx.conf \
      --network my_net \
      nginx
    

    配合 docker-gen 实现配置自动更新

5.3 持续部署流水线设计

典型CI/CD流程:

  1. 代码提交触发构建
  2. 单元测试与镜像构建
  3. 安全扫描(Trivy、Clair)
  4. 推送镜像到私有仓库
  5. 滚动更新生产环境
# 滚动更新示例
docker service update \
  --image myregistry/springboot-app:2.0 \
  --update-parallelism 2 \
  --update-delay 10s \
  app-service

6. 高级技巧与性能调优

6.1 资源限制策略

  1. 内存限制

    docker run -m 1g --memory-swap=1.5g ...
    

    注意:JVM需额外配置 -XX:MaxRAMPercentage=70.0 ,否则可能超出容器限制

  2. CPU分配

    docker run --cpus=1.5 ...  # 限制1.5个CPU核心
    docker run --cpuset-cpus="0-3" ...  # 绑定特定CPU核心
    

6.2 存储驱动选择

根据宿主机环境选择最优存储驱动:

驱动 适用场景 优点 缺点
overlay2 现代Linux内核(推荐) 性能好,支持xattr 需要内核>=4.0
aufs 旧版Ubuntu 兼容性好 性能较差
devicemapper CentOS/RHEL旧版本 企业级支持 需要额外配置
zfs ZFS文件系统用户 高级快照功能 内存消耗大

检查当前驱动:

docker info | grep "Storage Driver"

6.3 安全加固措施

  1. 只读文件系统

    docker run --read-only ...
    

    配合tmpfs挂载可写目录:

    docker run --read-only --tmpfs /tmp ...
    
  2. 能力限制

    docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE ...
    
  3. Seccomp策略

    docker run --security-opt seccomp=/path/to/profile.json ...
    

7. 监控与日志收集体系

7.1 Prometheus监控方案

  1. 容器暴露指标

    # docker-compose.yml
    ports:
      - "8080:8080"
      - "9090:9090"  # Prometheus监控端口
    
  2. Prometheus配置

    # prometheus.yml
    scrape_configs:
      - job_name: 'docker'
        static_configs:
          - targets: ['app-service:9090']
    

7.2 ELK日志收集

典型架构:

Filebeat(容器内) -> Logstash -> Elasticsearch -> Kibana

配置示例:

# Dockerfile
RUN curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.3.3-linux-x86_64.tar.gz \
    && tar xzvf filebeat-8.3.3-linux-x86_64.tar.gz \
    && mv filebeat-8.3.3-linux-x86_64 /usr/share/filebeat
COPY filebeat.yml /usr/share/filebeat/

7.3 分布式追踪集成

SpringBoot + SkyWalking示例:

# application.yml
spring:
  cloud:
    sleuth:
      enabled: true
    zipkin:
      base-url: http://zipkin:9411

management:
  metrics:
    export:
      zipkin:
        enabled: true

对应Docker部署:

docker run -d --name zipkin -p 9411:9411 openzipkin/zipkin

更多推荐