概述

本文提供完整的SpringBoot应用Docker容器化实战指南,涵盖从基础概念到生产环境部署的全流程。通过详细的代码示例和最佳实践,帮助开发者彻底解决环境不一致问题,构建可靠、可扩展的容器化应用。

环境准备与Docker安装

系统环境检查

在开始容器化之前,需要确保系统满足Docker运行的基本要求:

bash

#!/bin/bash
# docker_environment_check.sh - 环境检查脚本

set -euo pipefail

# 颜色定义
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'

echo -e "${BLUE}=== Docker环境检查开始 ===${NC}"

# 操作系统检查
echo -e "\n${GREEN}1. 操作系统检查${NC}"
if [ -f /etc/os-release ]; then
    source /etc/os-release
    echo -e "   操作系统: $NAME $VERSION"
    echo -e "   内核版本: $(uname -r)"
else
    echo -e "   ${YELLOW}警告: 无法确定操作系统类型${NC}"
fi

# 系统架构检查
echo -e "\n${GREEN}2. 系统架构检查${NC}"
ARCH=$(uname -m)
echo -e "   系统架构: $ARCH"

# 资源检查
echo -e "\n${GREEN}3. 系统资源检查${NC}"
MEM_TOTAL=$(free -h | awk 'NR==2{print $2}')
MEM_AVAILABLE=$(free -h | awk 'NR==2{print $7}')
echo -e "   总内存: $MEM_TOTAL"
echo -e "   可用内存: $MEM_AVAILABLE"

DISK_SPACE=$(df -h / | awk 'NR==2{print $4}')
echo -e "   根分区可用空间: $DISK_SPACE"

# Docker环境检查
echo -e "\n${GREEN}4. Docker环境检查${NC}"
check_docker_environment() {
    if command -v docker &> /dev/null; then
        DOCKER_VERSION=$(docker --version | cut -d' ' -f3 | tr -d ',')
        echo -e "   ✅ Docker已安装: $DOCKER_VERSION"
        
        if systemctl is-active --quiet docker; then
            echo -e "   ✅ Docker服务运行正常"
        else
            echo -e "   ${YELLOW}⚠️ Docker服务未运行${NC}"
        fi
    else
        echo -e "   ${RED}❌ Docker未安装${NC}"
    fi
    
    if command -v docker-compose &> /dev/null; then
        DOCKER_COMPOSE_VERSION=$(docker-compose --version | cut -d' ' -f3 | tr -d ',')
        echo -e "   ✅ Docker Compose已安装: $DOCKER_COMPOSE_VERSION"
    else
        echo -e "   ${YELLOW}⚠️ Docker Compose未安装${NC}"
    fi
}

check_docker_environment

echo -e "\n${BLUE}=== 环境检查完成 ===${NC}"

Docker自动化安装

提供跨平台的Docker安装脚本:

bash

#!/bin/bash
# install_docker.sh - Docker自动化安装脚本

set -euo pipefail

# 日志和颜色配置
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'

log() {
    echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}"
}

error_exit() {
    echo -e "${RED}错误: $1${NC}" >&2
    exit 1
}

# 操作系统检测
detect_os() {
    if [ -f /etc/os-release ]; then
        source /etc/os-release
        OS=$ID
        VERSION=$VERSION_ID
    else
        error_exit "无法检测操作系统"
    fi
}

# Docker安装主函数
install_docker() {
    log "开始安装Docker..."
    
    case $OS in
        ubuntu|debian)
            install_docker_debian
            ;;
        centos|rhel|fedora)
            install_docker_centos
            ;;
        *)
            error_exit "不支持的操作系统: $OS"
            ;;
    esac
}

# Ubuntu/Debian安装
install_docker_debian() {
    log "在Debian系系统上安装Docker..."
    
    # 清理旧版本
    sudo apt-get remove -y docker docker-engine docker.io containerd runc || true
    
    # 安装依赖
    sudo apt-get update
    sudo apt-get install -y \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg \
        lsb-release
    
    # 配置Docker仓库
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    
    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
    # 安装Docker引擎
    sudo apt-get update
    sudo apt-get install -y docker-ce docker-ce-cli containerd.io
    
    log "Docker安装完成"
}

# Docker Compose安装
install_docker_compose() {
    log "安装Docker Compose..."
    
    COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
    
    sudo curl -L "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" \
        -o /usr/local/bin/docker-compose
    
    sudo chmod +x /usr/local/bin/docker-compose
    sudo ln -sf /usr/local/bin/docker-compose /usr/bin/docker-compose
    
    log "Docker Compose ${COMPOSE_VERSION} 安装完成"
}

# Docker服务配置
configure_docker() {
    log "配置Docker服务..."
    
    sudo systemctl enable docker
    sudo systemctl start docker
    
    # 用户权限配置
    sudo usermod -aG docker $USER
    
    # 镜像加速器配置
    sudo mkdir -p /etc/docker
    sudo tee /etc/docker/daemon.json > /dev/null << EOF
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}
EOF
    
    sudo systemctl daemon-reload
    sudo systemctl restart docker
    
    log "Docker配置完成"
}

# 安装验证
verify_installation() {
    log "验证安装结果..."
    
    if docker --version && docker-compose --version; then
        log "✅ Docker环境安装成功"
        
        # 运行测试容器
        if docker run --rm hello-world; then
            log "✅ Docker运行测试通过"
        else
            error_exit "Docker运行测试失败"
        fi
    else
        error_exit "Docker安装验证失败"
    fi
}

main() {
    log "开始Docker自动化安装流程"
    
    detect_os
    install_docker
    install_docker_compose
    configure_docker
    verify_installation
    
    log "🎉 Docker安装全部完成!"
    log "请重新登录或执行 'newgrp docker' 使组权限生效"
}

main "$@"

SpringBoot应用容器化实战

示例应用开发

创建完整的SpringBoot演示应用:

java

// DemoApplication.java - 主应用类
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@RestController
class HealthController {
    
    @GetMapping("/health")
    public Map<String, Object> health() {
        Map<String, Object> healthInfo = new HashMap<>();
        healthInfo.put("status", "UP");
        healthInfo.put("timestamp", LocalDateTime.now().toString());
        healthInfo.put("service", "SpringBoot Docker Demo");
        return healthInfo;
    }
    
    @GetMapping("/info")
    public Map<String, Object> info() {
        Map<String, Object> info = new HashMap<>();
        info.put("java.version", System.getProperty("java.version"));
        info.put("os.name", System.getProperty("os.name"));
        info.put("availableProcessors", Runtime.getRuntime().availableProcessors());
        info.put("maxMemory", Runtime.getRuntime().maxMemory() / (1024 * 1024) + " MB");
        return info;
    }
}

应用配置

properties

# application.properties
spring.application.name=springboot-docker-demo
server.port=8080

# 监控端点配置
management.endpoint.health.enabled=true
management.endpoints.web.exposure.include=health,info,metrics

# 日志配置
logging.level.com.example.demo=INFO
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n

Maven构建配置

xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.example</groupId>
    <artifactId>springboot-docker-demo</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
    </parent>
    
    <properties>
        <java.version>11</java.version>
        <docker.image.prefix>springboot-demo</docker.image.prefix>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Docker容器化配置

生产级Dockerfile

dockerfile

# 多阶段构建Dockerfile
FROM maven:3.8.6-openjdk-11 AS builder

WORKDIR /app
COPY pom.xml .
# 利用Docker缓存层加速构建
RUN mvn dependency:go-offline -B

COPY src ./src
RUN mvn clean package -DskipTests

# 运行阶段
FROM openjdk:11-jre-slim

# 安全配置:使用非root用户
RUN groupadd -r springboot && useradd -r -g springboot springboot

# 时区配置
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

WORKDIR /app
COPY --from=builder --chown=springboot:springboot /app/target/*.jar app.jar
COPY --chown=springboot:springboot health-check.sh .

USER springboot

# JVM优化参数
ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
    CMD ./health-check.sh

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar app.jar"]

健康检查脚本

bash

#!/bin/bash
# health-check.sh

set -e

HEALTH_URL="http://localhost:8080/health"
TIMEOUT=5

response=$(curl -s -o /dev/null -w "%{http_code}" --max-time $TIMEOUT $HEALTH_URL || echo "000")

if [ "$response" = "200" ]; then
    echo "Health check: OK"
    exit 0
else
    echo "Health check: FAILED (HTTP $response)"
    exit 1
fi

自动化构建与部署

CI/CD构建脚本

bash

#!/bin/bash
# build_and_deploy.sh

set -euo pipefail

# 配置变量
APP_NAME="springboot-docker-demo"
VERSION="1.0.0"
REGISTRY="localhost:5000"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

# 构建应用
build_application() {
    log "构建SpringBoot应用..."
    mvn clean package -DskipTests
}

# 构建Docker镜像
build_docker_image() {
    log "构建Docker镜像..."
    local image_tag="$APP_NAME:$VERSION"
    docker build -t "$image_tag" .
    log "✅ 镜像构建成功: $image_tag"
}

# 运行测试
run_tests() {
    log "运行容器测试..."
    
    local test_container="${APP_NAME}-test"
    local image_tag="$APP_NAME:$VERSION"
    
    docker run -d --name "$test_container" -p 8081:8080 "$image_tag"
    sleep 30
    
    # 健康检查测试
    local health_response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8081/health)
    if [ "$health_response" = "200" ]; then
        log "✅ 健康检查通过"
    else
        docker logs "$test_container"
        error_exit "健康检查失败"
    fi
    
    docker stop "$test_container"
    docker rm "$test_container"
}

# 部署到环境
deploy_environment() {
    local environment=$1
    log "部署到 $environment 环境..."
    
    case $environment in
        dev)
            docker run -d --name "${APP_NAME}-dev" -p 8080:8080 "$APP_NAME:$VERSION"
            ;;
        prod)
            docker-compose -f docker-compose.prod.yml up -d
            ;;
    esac
}

main() {
    local environment=${1:-dev}
    
    log "开始应用部署流程..."
    
    build_application
    build_docker_image
    run_tests
    deploy_environment $environment
    
    log "🎉 应用部署完成!"
}

main "$@"

Docker Compose编排

开发环境配置

yaml

# docker-compose.dev.yml
version: '3.8'

services:
  app:
    build: .
    image: springboot-docker-demo:dev
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=dev
      - JAVA_OPTS=-Xms256m -Xmx512m
    networks:
      - app-network

  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=app_db
    ports:
      - "3306:3306"
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

生产环境配置

yaml

# docker-compose.prod.yml
version: '3.8'

services:
  app:
    image: springboot-docker-demo:${VERSION:-latest}
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - JAVA_OPTS=-Xms512m -Xmx1024m
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: '1.0'
    healthcheck:
      test: ["CMD", "./health-check.sh"]
      interval: 30s
      timeout: 10s
      retries: 3

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - app

监控与运维

应用监控配置

yaml

# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'springboot-app'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['app:8080']

日志管理

bash

#!/bin/bash
# log_manager.sh

view_logs() {
    docker logs -f springboot-app
}

export_logs() {
    local timestamp=$(date +%Y%m%d_%H%M%S)
    docker logs springboot-app > "logs/app_${timestamp}.log"
}

analyze_logs() {
    docker logs springboot-app | grep "ERROR" | head -20
}

case "${1:-help}" in
    view)
        view_logs
        ;;
    export)
        export_logs
        ;;
    analyze)
        analyze_logs
        ;;
    *)
        echo "用法: $0 {view|export|analyze}"
        ;;
esac

安全加固配置

安全增强Dockerfile

dockerfile

FROM openjdk:11-jre-slim

# 安全更新
RUN apt-get update && apt-get upgrade -y && apt-get clean

# 非特权用户
RUN groupadd -r appuser && useradd -r -g appuser appuser

USER appuser

WORKDIR /app
COPY --chown=appuser:appuser app.jar .

EXPOSE 8080

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

部署架构总结

通过本指南,您将掌握:

核心能力

  1. 环境标准化 - 一致的开发、测试、生产环境

  2. 自动化流程 - 完整的CI/CD流水线

  3. 生产就绪 - 监控、日志、安全加固

  4. 最佳实践 - 遵循Docker和SpringBoot规范

关键特性

  • ✅ 持续集成自动化

  • ✅ 多阶段构建优化

  • ✅ 健康检查机制

  • ✅ 资源限制配置

  • ✅ 安全最佳实践

后续步骤

  1. 配置完整的CI/CD流水线

  2. 实施容器安全扫描

  3. 配置自动扩缩容

  4. 建立监控告警体系

现在您可以 confidently 将SpringBoot应用容器化,享受Docker带来的环境一致性和部署便利性!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐