Spring Boot 应用 Docker 部署完整指南

Spring Boot 应用 Docker 部署完整指南

本文档提供从零开始的 Docker 部署完整流程,包括环境检查、旧服务清理、镜像构建、容器运行及故障排查。


目录

  1. 环境准备与检查
  2. 目录结构规划
  3. [Dockerfile 编写规范](#Dockerfile 编写规范)
  4. 旧服务清理流程
  5. 镜像构建与验证
  6. 容器运行配置
  7. 部署验证与检查
  8. 自动化部署脚本
  9. 常用管理命令
  10. 故障排查指南

一、环境准备与检查

1.1 检查 Docker 环境

bash 复制代码
# 检查 Docker 版本
docker --version

# 检查 Docker 服务状态
systemctl status docker

# 如果 Docker 未启动,执行启动
systemctl start docker
systemctl enable docker

# 检查当前运行的容器
docker ps -a

# 检查现有镜像
docker images

1.2 检查系统资源

bash 复制代码
# 检查磁盘空间
df -h

# 检查内存使用
free -h

# 检查 Docker 存储使用情况
docker system df

1.3 检查端口占用

bash 复制代码
# 检查应用端口是否被占用(假设应用端口是 8089)
netstat -tlnp | grep 8089
lsof -i:8089

# 如果端口被占用且需要释放
kill -9 <PID>

1.4 检查基础镜像

bash 复制代码
# 检查是否有 OpenJDK 17 镜像
docker images | grep openjdk

# 如果没有,拉取镜像
docker pull openjdk:17.0.2

二、目录结构规划

2.1 创建项目目录

bash 复制代码
# 创建主目录
mkdir -p /home/smart-brain

# 创建数据挂载目录(根据实际需求)
mkdir -p /home/rkg/templateFile

# 创建日志目录(可选)
mkdir -p /home/smart-brain/logs

# 创建备份目录
mkdir -p /home/smart-brain/backup

2.2 目录结构说明

复制代码
/home/smart-brain/              # 主目录
├── Dockerfile                  # Docker 构建文件
├── greatek-smart-brain-1.0.jar # 应用 jar 包
├── deploy.sh                   # 自动化部署脚本
├── logs/                       # 日志目录(可选)
└── backup/                     # 备份目录

/home/rkg/templateFile/         # 数据挂载目录

2.3 设置目录权限

bash 复制代码
# 设置目录权限
chmod 755 /home/smart-brain
chmod 755 /home/rkg/templateFile

# 查看权限
ls -ld /home/smart-brain
ls -ld /home/rkg/templateFile

三、Dockerfile 编写规范

3.1 Dockerfile 基本结构

Dockerfile 是纯文本文件,不包含任何 shell 命令(如 cd、ls 等),只包含 Docker 指令。

3.2 创建标准 Dockerfile

bash 复制代码
cd /home/smart-brain

# 方法一:使用 cat 命令创建(推荐)
cat > Dockerfile << 'EOF'
FROM openjdk:17.0.2

LABEL authors="greatek"

WORKDIR /rkg

ENV JAVA_OPTS="-Dfile.encoding=UTF-8 \
    -Dsun.jnu.encoding=UTF-8 \
    -Duser.language=zh \
    -Duser.country=CN \
    -Duser.timezone=Asia/Shanghai \
    -Djava.security.egd=file:/dev/./urandom"

COPY greatek-smart-brain-1.0.jar app.jar

VOLUME ["/home/rkg/templateFile"]

EXPOSE 8089

ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
EOF
bash 复制代码
# 方法二:使用 vi 编辑器创建
vi Dockerfile

# 按 i 进入编辑模式,粘贴上面的内容
# 按 ESC 退出编辑模式
# 输入 :wq 保存退出

3.3 Dockerfile 指令说明

指令 说明 示例
FROM 基础镜像 FROM openjdk:17.0.2
LABEL 元数据标签 LABEL authors="greatek"
WORKDIR 工作目录 WORKDIR /rkg
ENV 环境变量 ENV JAVA_OPTS="-Dfile.encoding=UTF-8"
COPY 复制文件到镜像 COPY app.jar app.jar
VOLUME 数据卷挂载点 VOLUME ["/data"]
EXPOSE 暴露端口(文档用途) EXPOSE 8089
ENTRYPOINT 容器启动命令 ENTRYPOINT ["java", "-jar", "app.jar"]

3.4 验证 Dockerfile

bash 复制代码
# 查看 Dockerfile 内容(第一行必须是 FROM)
cat Dockerfile

# 检查文件格式(不应有 Windows 换行符)
file Dockerfile

# 如果有 Windows 换行符,转换格式
dos2unix Dockerfile

# 检查是否有隐藏字符
hexdump -C Dockerfile | head -20

3.5 常见错误避免

错误示例(包含 shell 命令):

dockerfile 复制代码
cd /home/smart-brain
FROM openjdk:17.0.2

正确示例

dockerfile 复制代码
FROM openjdk:17.0.2
LABEL authors="greatek"

关键点

  • Dockerfile 第一行必须是 FROM 指令
  • 不能包含 cdlsecho 等 shell 命令
  • 每行指令独立,不能有 shell 脚本语法

四、旧服务清理流程

4.1 查看现有服务

bash 复制代码
# 查看运行中的容器
docker ps

# 查看所有容器(包括已停止)
docker ps -a

# 查看指定容器
docker ps -a | grep abnormal-monitoring

# 查看现有镜像
docker images | grep abnormal-monitoring

4.2 备份旧服务数据

bash 复制代码
# 备份容器日志
docker logs abnormal-monitoring > /home/smart-brain/backup/abnormal-monitoring-$(date +%Y%m%d-%H%M%S).log 2>&1

# 导出旧镜像(可选,用于回滚)
docker save abnormal-monitoring:v0.0.1 -o /home/smart-brain/backup/abnormal-monitoring-v0.0.1.tar

# 备份容器配置
docker inspect abnormal-monitoring > /home/smart-brain/backup/abnormal-monitoring-config-$(date +%Y%m%d-%H%M%S).json

4.3 停止旧容器

bash 复制代码
# 优雅停止容器(等待 10 秒)
docker stop abnormal-monitoring

# 强制停止容器
docker stop -t 0 abnormal-monitoring

# 验证容器已停止
docker ps | grep abnormal-monitoring

4.4 删除旧容器

bash 复制代码
# 删除容器
docker rm abnormal-monitoring

# 强制删除(即使容器正在运行)
docker rm -f abnormal-monitoring

# 验证容器已删除
docker ps -a | grep abnormal-monitoring

4.5 删除旧镜像

bash 复制代码
# 查看镜像 ID
docker images | grep abnormal-monitoring

# 按标签删除
docker rmi abnormal-monitoring:v0.0.1

# 按镜像 ID 删除
docker rmi ed1067cecd0b

# 强制删除
docker rmi -f abnormal-monitoring:v0.0.1

# 验证镜像已删除
docker images | grep abnormal-monitoring

4.6 清理无用资源

bash 复制代码
# 清理悬空镜像(<none>)
docker image prune

# 清理停止的容器
docker container prune

# 清理未使用的卷
docker volume prune

# 清理所有未使用资源(慎用)
docker system prune -a

4.7 完整清理脚本

bash 复制代码
# 创建清理脚本
cat > /home/smart-brain/cleanup.sh << 'EOF'
#!/bin/bash

echo "=========================================="
echo "  清理旧服务"
echo "=========================================="

CONTAINER_NAME="abnormal-monitoring"
IMAGE_NAME="abnormal-monitoring:v0.0.1"

# 1. 备份日志
if docker ps -a | grep -q $CONTAINER_NAME; then
    echo "1. 备份容器日志..."
    docker logs $CONTAINER_NAME > /home/smart-brain/backup/backup-$(date +%Y%m%d-%H%M%S).log 2>&1
    echo "   日志已备份"
fi

# 2. 停止容器
echo "2. 停止容器..."
docker stop $CONTAINER_NAME 2>/dev/null || echo "   容器未运行"

# 3. 删除容器
echo "3. 删除容器..."
docker rm $CONTAINER_NAME 2>/dev/null || echo "   容器不存在"

# 4. 删除镜像
echo "4. 删除镜像..."
docker rmi $IMAGE_NAME 2>/dev/null || echo "   镜像不存在"

# 5. 清理悬空镜像
echo "5. 清理悬空镜像..."
docker image prune -f

echo ""
echo "清理完成!"
echo ""
EOF

chmod +x /home/smart-brain/cleanup.sh

# 执行清理
/home/smart-brain/cleanup.sh

五、镜像构建与验证

5.1 准备构建文件

bash 复制代码
cd /home/smart-brain

# 确认文件存在
ls -lh

# 应该看到:
# - Dockerfile
# - greatek-smart-brain-1.0.jar

# 检查 jar 包完整性
file greatek-smart-brain-1.0.jar

5.2 构建镜像

bash 复制代码
cd /home/smart-brain

# 基本构建命令
docker build -t abnormal-monitoring:v0.0.1 .

# 不使用缓存构建
docker build --no-cache -t abnormal-monitoring:v0.0.1 .

# 指定 Dockerfile 位置
docker build -f Dockerfile -t abnormal-monitoring:v0.0.1 .

5.3 构建输出解读

正常构建输出

复制代码
Sending build context to Docker daemon  125.2MB
Step 1/8 : FROM openjdk:17.0.2
 ---> 5e28ba2b4cdb
Step 2/8 : LABEL authors="greatek"
 ---> Running in a1b2c3d4e5f6
 ---> Removed intermediate container a1b2c3d4e5f6
 ---> 1234567890ab
...
Step 8/8 : ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
 ---> Running in f6e5d4c3b2a1
 ---> Removed intermediate container f6e5d4c3b2a1
 ---> abcdef123456
Successfully built abcdef123456
Successfully tagged abnormal-monitoring:v0.0.1

5.4 验证镜像

bash 复制代码
# 查看镜像
docker images | grep abnormal-monitoring

# 查看镜像详细信息
docker inspect abnormal-monitoring:v0.0.1

# 查看镜像历史
docker history abnormal-monitoring:v0.0.1

# 查看镜像层
docker image inspect abnormal-monitoring:v0.0.1 --format='{{.RootFS.Layers}}'

5.5 镜像测试(可选)

bash 复制代码
# 临时启动容器测试镜像
docker run --rm -it abnormal-monitoring:v0.0.1 java -version

# 查看镜像内文件
docker run --rm -it abnormal-monitoring:v0.0.1 ls -lh /rkg/

# 测试应用启动(短暂运行)
docker run --rm abnormal-monitoring:v0.0.1 --help

5.6 构建错误处理

错误 1:Dockerfile 解析错误

复制代码
Error response from daemon: dockerfile parse error on line 1: unknown instruction: cd

解决:删除 Dockerfile 中的 shell 命令,重新创建。

错误 2:找不到 jar 包

复制代码
COPY failed: file not found

解决:检查 jar 包文件名是否正确,或修改 Dockerfile 中的 COPY 指令。

错误 3:基础镜像拉取失败

复制代码
Error response from daemon: pull access denied

解决 :手动拉取基础镜像 docker pull openjdk:17.0.2


六、容器运行配置

6.1 网络模式选择

Host 网络模式(推荐用于单机部署)

特点

  • 容器直接使用宿主机网络
  • 无需端口映射
  • 性能最优
  • 容器内使用 localhost 访问宿主机服务
bash 复制代码
docker run -dit \
  --name abnormal-monitoring \
  --network host \
  --restart=unless-stopped \
  -v /home/rkg/templateFile:/home/rkg/templateFile \
  abnormal-monitoring:v0.0.1
Bridge 网络模式(适用于多容器隔离)

特点

  • 容器使用独立网络
  • 需要端口映射
  • 容器间隔离
  • 使用容器 IP 或容器名通信
bash 复制代码
docker run -dit \
  --name abnormal-monitoring \
  -p 8089:8089 \
  --restart=unless-stopped \
  -v /home/rkg/templateFile:/home/rkg/templateFile \
  abnormal-monitoring:v0.0.1

6.2 容器启动参数详解

bash 复制代码
docker run -dit \
  --name abnormal-monitoring \          # 容器名称
  --network host \                      # 网络模式
  --restart=unless-stopped \            # 重启策略
  -e SPRING_PROFILES_ACTIVE=prod \      # 环境变量
  -e TZ=Asia/Shanghai \                 # 时区设置
  -v /home/rkg/templateFile:/home/rkg/templateFile \  # 数据卷挂载
  -v /home/smart-brain/logs:/rkg/logs \ # 日志挂载(可选)
  --memory="2g" \                       # 内存限制(可选)
  --cpus="2" \                          # CPU 限制(可选)
  abnormal-monitoring:v0.0.1            # 镜像名

6.3 重启策略说明

策略 说明 使用场景
no 不自动重启(默认) 测试环境
always 总是重启 关键服务
unless-stopped 除非手动停止,否则重启 生产环境推荐
on-failure[:max-retries] 失败时重启 需要控制重启次数

6.4 环境变量配置

bash 复制代码
# 常用环境变量
-e SPRING_PROFILES_ACTIVE=prod          # Spring 配置文件
-e JAVA_OPTS="-Xmx2g -Xms2g"           # JVM 参数
-e TZ=Asia/Shanghai                     # 时区
-e NACOS_SERVER_ADDR=127.0.0.1:8848    # Nacos 地址
-e REDIS_HOST=127.0.0.1                # Redis 地址

6.5 数据卷挂载

bash 复制代码
# 挂载单个目录
-v /home/rkg/templateFile:/home/rkg/templateFile

# 挂载多个目录
-v /home/rkg/templateFile:/home/rkg/templateFile \
-v /home/smart-brain/logs:/rkg/logs \
-v /home/smart-brain/config:/rkg/config

# 只读挂载
-v /home/smart-brain/config:/rkg/config:ro

6.6 完整启动命令(生产环境)

bash 复制代码
docker run -dit \
  --name abnormal-monitoring \
  --network host \
  --restart=unless-stopped \
  -e SPRING_PROFILES_ACTIVE=prod \
  -e TZ=Asia/Shanghai \
  -e JAVA_OPTS="-Xmx2g -Xms2g -XX:+UseG1GC" \
  -v /home/rkg/templateFile:/home/rkg/templateFile \
  -v /home/smart-brain/logs:/rkg/logs \
  --memory="4g" \
  --cpus="2" \
  abnormal-monitoring:v0.0.1

七、部署验证与检查

7.1 容器状态检查

bash 复制代码
# 查看运行状态
docker ps | grep abnormal-monitoring

# 查看详细信息
docker inspect abnormal-monitoring

# 查看容器资源使用
docker stats abnormal-monitoring --no-stream

# 查看容器进程
docker top abnormal-monitoring

7.2 日志检查

bash 复制代码
# 实时查看日志(Ctrl+C 退出)
docker logs -f abnormal-monitoring

# 查看最近 100 行日志
docker logs --tail 100 abnormal-monitoring

# 查看带时间戳的日志
docker logs -f --timestamps abnormal-monitoring

# 查看指定时间后的日志
docker logs --since "2024-12-10T10:00:00" abnormal-monitoring

# 导出日志到文件
docker logs abnormal-monitoring > /home/smart-brain/app.log 2>&1

7.3 应用健康检查

bash 复制代码
# 检查端口监听(host 网络模式)
netstat -tlnp | grep java
ss -tlnp | grep java
lsof -i:8089

# 测试应用接口
curl http://localhost:8089/actuator/health

# 测试根路径
curl http://localhost:8089/

# 查看应用版本信息
curl http://localhost:8089/actuator/info

7.4 进入容器检查

bash 复制代码
# 进入容器
docker exec -it abnormal-monitoring /bin/bash

# 在容器内执行检查
pwd                                    # 查看当前目录
ls -lh                                 # 查看文件
ps aux | grep java                     # 查看进程
netstat -tlnp                          # 查看端口
cat /etc/hosts                         # 查看 hosts
env                                    # 查看环境变量
java -version                          # 查看 Java 版本
ls -la /home/rkg/templateFile          # 查看挂载目录

# 退出容器
exit

7.5 服务注册检查(如果使用 Nacos)

bash 复制代码
# 查看 Nacos 服务列表
curl "http://localhost:8848/nacos/v1/ns/instance/list?serviceName=abnormal-monitoring"

# 查看服务详情
curl "http://localhost:8848/nacos/v1/ns/instance?serviceName=abnormal-monitoring"

# 浏览器访问 Nacos 控制台
# http://服务器IP:8848/nacos
# 默认账号密码:nacos/nacos

7.6 性能监控

bash 复制代码
# 实时监控容器资源
docker stats abnormal-monitoring

# 查看容器磁盘使用
docker exec abnormal-monitoring df -h

# 查看应用内存使用
docker exec abnormal-monitoring free -h

# 查看 JVM 内存
docker exec abnormal-monitoring jstat -gc <PID>

7.7 连接其他服务测试

bash 复制代码
# 进入容器测试连接
docker exec -it abnormal-monitoring /bin/bash

# 测试 Nacos 连接
curl http://127.0.0.1:8848/nacos/v1/console/health/readiness

# 测试 Redis 连接
telnet 127.0.0.1 6379
# 或
redis-cli -h 127.0.0.1 -p 6379 ping

# 测试数据库连接(如果有 psql)
psql -h 127.0.0.1 -U username -d database

exit

八、自动化部署脚本

8.1 完整自动化部署脚本

bash 复制代码
cat > /home/smart-brain/deploy.sh << 'EOF'
#!/bin/bash

#============================================
# Spring Boot Docker 自动化部署脚本
# 作者: Greatek
# 版本: v1.0
# 说明: 用于自动化部署 Spring Boot 应用到 Docker
#============================================

set -e  # 遇到错误立即退出

#============================================
# 配置区域(根据实际情况修改)
#============================================
CONTAINER_NAME="abnormal-monitoring"
IMAGE_NAME="abnormal-monitoring"
IMAGE_TAG="v0.0.1"
JAR_FILE="greatek-smart-brain-1.0.jar"
APP_PORT="8089"
WORK_DIR="/home/smart-brain"
BACKUP_DIR="${WORK_DIR}/backup"
VOLUME_DIR="/home/rkg/templateFile"

#============================================
# 颜色输出
#============================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

#============================================
# 1. 环境检查
#============================================
check_environment() {
    log_info "=========================================="
    log_info "  环境检查"
    log_info "=========================================="
    
    # 检查 Docker
    if ! command -v docker &> /dev/null; then
        log_error "Docker 未安装,请先安装 Docker"
        exit 1
    fi
    log_info "✓ Docker 已安装: $(docker --version)"
    
    # 检查 Docker 服务
    if ! systemctl is-active --quiet docker; then
        log_error "Docker 服务未运行,请启动 Docker: systemctl start docker"
        exit 1
    fi
    log_info "✓ Docker 服务运行正常"
    
    # 检查工作目录
    if [ ! -d "$WORK_DIR" ]; then
        log_error "工作目录不存在: $WORK_DIR"
        exit 1
    fi
    log_info "✓ 工作目录存在: $WORK_DIR"
    
    # 检查 jar 包
    if [ ! -f "$WORK_DIR/$JAR_FILE" ]; then
        log_error "jar 包不存在: $WORK_DIR/$JAR_FILE"
        exit 1
    fi
    log_info "✓ jar 包存在: $JAR_FILE ($(ls -lh $WORK_DIR/$JAR_FILE | awk '{print $5}'))"
    
    # 检查 Dockerfile
    if [ ! -f "$WORK_DIR/Dockerfile" ]; then
        log_error "Dockerfile 不存在: $WORK_DIR/Dockerfile"
        exit 1
    fi
    log_info "✓ Dockerfile 存在"
    
    # 检查挂载目录
    if [ ! -d "$VOLUME_DIR" ]; then
        log_warn "挂载目录不存在,正在创建: $VOLUME_DIR"
        mkdir -p "$VOLUME_DIR"
    fi
    log_info "✓ 挂载目录存在: $VOLUME_DIR"
    
    # 检查备份目录
    if [ ! -d "$BACKUP_DIR" ]; then
        mkdir -p "$BACKUP_DIR"
        log_info "✓ 创建备份目录: $BACKUP_DIR"
    fi
    
    echo ""
}

#============================================
# 2. 备份旧服务
#============================================
backup_old_service() {
    log_info "=========================================="
    log_info "  备份旧服务"
    log_info "=========================================="
    
    if docker ps -a | grep -q "$CONTAINER_NAME"; then
        TIMESTAMP=$(date +%Y%m%d-%H%M%S)
        
        # 备份日志
        log_info "备份容器日志..."
        docker logs "$CONTAINER_NAME" > "$BACKUP_DIR/${CONTAINER_NAME}-${TIMESTAMP}.log" 2>&1
        log_info "✓ 日志已备份: ${CONTAINER_NAME}-${TIMESTAMP}.log"
        
        # 备份配置
        log_info "备份容器配置..."
        docker inspect "$CONTAINER_NAME" > "$BACKUP_DIR/${CONTAINER_NAME}-config-${TIMESTAMP}.json"
        log_info "✓ 配置已备份: ${CONTAINER_NAME}-config-${TIMESTAMP}.json"
    else
        log_warn "未找到运行中的容器,跳过备份"
    fi
    
    # 清理旧备份(保留最近 5 个)
    log_info "清理旧备份文件(保留最近 5 个)..."
    cd "$BACKUP_DIR"
    ls -t ${CONTAINER_NAME}-*.log 2>/dev/null | tail -n +6 | xargs -r rm -f
    ls -t ${CONTAINER_NAME}-config-*.json 2>/dev/null | tail -n +6 | xargs -r rm -f
    
    echo ""
}

#============================================
# 3. 停止并删除旧容器
#============================================
remove_old_container() {
    log_info "=========================================="
    log_info "  清理旧容器"
    log_info "=========================================="
    
    if docker ps -a | grep -q "$CONTAINER_NAME"; then
        # 停止容器
        log_info "停止容器: $CONTAINER_NAME"
        docker stop "$CONTAINER_NAME" 2>/dev/null || true
        log_info "✓ 容器已停止"
        
        # 删除容器
        log_info "删除容器: $CONTAINER_NAME"
        docker rm "$CONTAINER_NAME" 2>/dev/null || true
        log_info "✓ 容器已删除"
    else
        log_warn "容器不存在,跳过删除"
    fi
    
    echo ""
}

#============================================
# 4. 删除旧镜像
#============================================
remove_old_image() {
    log_info "=========================================="
    log_info "  清理旧镜像"
    log_info "=========================================="
    
    if docker images | grep -q "$IMAGE_NAME.*$IMAGE_TAG"; then
        log_info "删除镜像: ${IMAGE_NAME}:${IMAGE_TAG}"
        docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2>/dev/null || true
        log_info "✓ 镜像已删除"
    else
        log_warn "镜像不存在,跳过删除"
    fi
    
    # 清理悬空镜像
    log_info "清理悬空镜像..."
    docker image prune -f > /dev/null 2>&1
    log_info "✓ 悬空镜像已清理"
    
    echo ""
}

#============================================
# 5. 构建新镜像
#============================================
build_image() {
    log_info "=========================================="
    log_info "  构建新镜像"
    log_info "=========================================="
    
    cd "$WORK_DIR"
    
    log_info "开始构建镜像: ${IMAGE_NAME}:${IMAGE_TAG}"
    log_info "构建上下文: $WORK_DIR"
    
    if docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" .; then
        log_info "✓ 镜像构建成功"
        
        # 显示镜像信息
        IMAGE_SIZE=$(docker images "${IMAGE_NAME}:${IMAGE_TAG}" --format "{{.Size}}")
        log_info "镜像大小: $IMAGE_SIZE"
    else
        log_error "镜像构建失败"
        exit 1
    fi
    
    echo ""
}

#============================================
# 6. 启动新容器
#============================================
start_container() {
    log_info "=========================================="
    log_info "  启动新容器"
    log_info "=========================================="
    
    log_info "启动容器: $CONTAINER_NAME"
    log_info "网络模式: host"
    log_info "重启策略: unless-stopped"
    log_info "数据挂载: $VOLUME_DIR"
    
    docker run -dit \
      --name "$CONTAINER_NAME" \
      --network host \
      --restart=unless-stopped \
      -e TZ=Asia/Shanghai \
      -v "${VOLUME_DIR}:${VOLUME_DIR}" \
      "${IMAGE_NAME}:${IMAGE_TAG}"
    
    if [ $? -eq 0 ]; then
        log_info "✓ 容器启动成功"
    else
        log_error "容器启动失败"
        exit 1
    fi
    
    echo ""
}

#============================================
# 7. 等待应用启动
#============================================
wait_for_app() {
    log_info "=========================================="
    log_info "  等待应用启动"
    log_info "=========================================="
    
    log_info "等待应用启动(最多等待 60 秒)..."
    
    for i in {1..60}; do
        sleep 1
        if docker ps | grep -q "$CONTAINER_NAME"; then
            # 检查端口是否监听(仅适用于 host 网络)
            if netstat -tlnp 2>/dev/null | grep -q ":${APP_PORT}"; then
                log_info "✓ 应用启动成功(${i}秒)"
                return 0
            fi
        else
            log_error "容器已停止"
            docker logs --tail 50 "$CONTAINER_NAME"
            exit 1
        fi
        
        # 每 10 秒显示一次进度
        if [ $((i % 10)) -eq 0 ]; then
            log_info "仍在等待... (${i}/60 秒)"
        fi
    done
    
    log_warn "应用启动超时,请检查日志"
    echo ""
}

#============================================
# 8. 验证部署
#============================================
verify_deployment() {
    log_info "=========================================="
    log_info "  验证部署"
    log_info "=========================================="
    
    # 检查容器状态
    if docker ps | grep -q "$CONTAINER_NAME"; then
        log_info "✓ 容器运行正常"
        docker ps | grep "$CONTAINER_NAME"
    else
        log_error "✗ 容器未运行"
        exit 1
    fi
    
    echo ""
    
    # 检查端口
    if netstat -tlnp 2>/dev/null | grep -q ":${APP_PORT}"; then
        log_info "✓ 端口监听正常: $APP_PORT"
    else
        log_warn "✗ 端口未监听: $APP_PORT"
    fi
    
    echo ""
    
    # 显示最近日志
    log_info "最近 20 行日志:"
    docker logs --tail 20 "$CONTAINER_NAME"
    
    echo ""
}

#============================================
# 9. 部署总结
#============================================
show_summary() {
    log_info "=========================================="
    log_info "  部署完成"
    log_info "=========================================="
    echo ""
    echo "容器名称: $CONTAINER_NAME"
    echo "镜像: ${IMAGE_NAME}:${IMAGE_TAG}"
    echo "应用端口: $APP_PORT"
    echo "网络模式: host"
    echo ""
    echo "常用命令:"
    echo "  查看日志: docker logs -f $CONTAINER_NAME"
    echo "  查看状态: docker ps | grep $CONTAINER_NAME"
    echo "  重启服务: docker restart $CONTAINER_NAME"
    echo "  停止服务: docker stop $CONTAINER_NAME"
    echo "  进入容器: docker exec -it $CONTAINER_NAME /bin/bash"
    echo ""
    echo "应用访问:"
    echo "  http://localhost:${APP_PORT}"
    echo ""
}

#============================================
# 主流程
#============================================
main() {
    echo ""
    log_info "=========================================="
    log_info "  Spring Boot Docker 自动化部署"
    log_info "  开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
    log_info "=========================================="
    echo ""
    
    # 执行部署流程
    check_environment
    backup_old_service
    remove_old_container
    remove_old_image
    build_image
    start_container
    wait_for_app
    verify_deployment
    show_summary
    
    log_info "部署完成时间: $(date '+%Y-%m-%d %H:%M:%S')"
    echo ""
}

# 执行主流程
main

EOF

# 赋予执行权限
chmod +x /home/smart-brain/deploy.sh

8.2 快速部署脚本(精简版)

bash 复制代码
cat > /home/smart-brain/quick-deploy.sh << 'EOF'
#!/bin/bash

set -e

CONTAINER_NAME="abnormal-monitoring"
IMAGE_NAME="abnormal-monitoring:v0.0.1"
WORK_DIR="/home/smart-brain"

echo "=== 快速部署 ==="

cd "$WORK_DIR"

# 停止并删除旧容器
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm "$CONTAINER_NAME" 2>/dev/null || true

# 删除旧镜像
docker rmi "$IMAGE_NAME" 2>/dev/null || true

# 构建新镜像
echo "构建镜像..."
docker build -t "$IMAGE_NAME" .

# 启动容器
echo "启动容器..."
docker run -dit \
  --name "$CONTAINER_NAME" \
  --network host \
  --restart=unless-stopped \
  -v /home/rkg/templateFile:/home/rkg/templateFile \
  "$IMAGE_NAME"

# 等待启动
sleep 5

# 检查状态
docker ps | grep "$CONTAINER_NAME"

echo "=== 部署完成 ==="
echo "查看日志: docker logs -f $CONTAINER_NAME"

EOF

chmod +x /home/smart-brain/quick-deploy.sh

8.3 回滚脚本

bash 复制代码
cat > /home/smart-brain/rollback.sh << 'EOF'
#!/bin/bash

set -e

CONTAINER_NAME="abnormal-monitoring"
BACKUP_DIR="/home/smart-brain/backup"

echo "=== 回滚到旧版本 ==="

# 查找最新的备份镜像
LATEST_BACKUP=$(ls -t "$BACKUP_DIR"/*.tar 2>/dev/null | head -1)

if [ -z "$LATEST_BACKUP" ]; then
    echo "错误: 未找到备份镜像"
    exit 1
fi

echo "找到备份: $LATEST_BACKUP"

# 停止当前容器
echo "停止当前容器..."
docker stop "$CONTAINER_NAME"
docker rm "$CONTAINER_NAME"

# 加载备份镜像
echo "加载备份镜像..."
docker load -i "$LATEST_BACKUP"

# 启动容器
echo "启动容器..."
docker run -dit \
  --name "$CONTAINER_NAME" \
  --network host \
  --restart=unless-stopped \
  -v /home/rkg/templateFile:/home/rkg/templateFile \
  abnormal-monitoring:v0.0.1

echo "=== 回滚完成 ==="

EOF

chmod +x /home/smart-brain/rollback.sh

8.4 使用脚本

bash 复制代码
# 完整部署(推荐)
/home/smart-brain/deploy.sh

# 快速部署
/home/smart-brain/quick-deploy.sh

# 回滚
/home/smart-brain/rollback.sh

九、常用管理命令

9.1 容器管理

bash 复制代码
# 查看所有容器
docker ps -a

# 查看运行中的容器
docker ps

# 启动容器
docker start abnormal-monitoring

# 停止容器
docker stop abnormal-monitoring

# 重启容器
docker restart abnormal-monitoring

# 强制停止容器
docker kill abnormal-monitoring

# 删除容器
docker rm abnormal-monitoring

# 强制删除运行中的容器
docker rm -f abnormal-monitoring

# 暂停容器
docker pause abnormal-monitoring

# 恢复容器
docker unpause abnormal-monitoring

9.2 日志管理

bash 复制代码
# 实时查看日志
docker logs -f abnormal-monitoring

# 查看最后 100 行
docker logs --tail 100 abnormal-monitoring

# 查看带时间戳的日志
docker logs -f --timestamps abnormal-monitoring

# 查看指定时间后的日志
docker logs --since "2024-12-10T10:00:00" abnormal-monitoring
docker logs --since "1h" abnormal-monitoring

# 查看指定时间范围的日志
docker logs --since "2024-12-10T10:00:00" --until "2024-12-10T12:00:00" abnormal-monitoring

# 导出日志
docker logs abnormal-monitoring > app.log 2>&1

9.3 容器操作

bash 复制代码
# 进入容器
docker exec -it abnormal-monitoring /bin/bash

# 在容器中执行命令
docker exec abnormal-monitoring ls -la /rkg

# 查看容器进程
docker top abnormal-monitoring

# 查看容器资源使用
docker stats abnormal-monitoring

# 查看容器详细信息
docker inspect abnormal-monitoring

# 复制文件到容器
docker cp /path/to/file abnormal-monitoring:/rkg/

# 从容器复制文件
docker cp abnormal-monitoring:/rkg/file /path/to/

9.4 镜像管理

bash 复制代码
# 查看所有镜像
docker images

# 查看镜像详情
docker inspect abnormal-monitoring:v0.0.1

# 查看镜像历史
docker history abnormal-monitoring:v0.0.1

# 删除镜像
docker rmi abnormal-monitoring:v0.0.1

# 强制删除镜像
docker rmi -f abnormal-monitoring:v0.0.1

# 导出镜像
docker save abnormal-monitoring:v0.0.1 -o abnormal-monitoring.tar

# 导入镜像
docker load -i abnormal-monitoring.tar

# 给镜像打标签
docker tag abnormal-monitoring:v0.0.1 abnormal-monitoring:latest

9.5 清理命令

bash 复制代码
# 清理停止的容器
docker container prune

# 清理悬空镜像
docker image prune

# 清理未使用的卷
docker volume prune

# 清理未使用的网络
docker network prune

# 清理所有未使用资源
docker system prune

# 清理所有未使用资源(包括未使用的镜像)
docker system prune -a

# 查看 Docker 磁盘使用
docker system df

# 查看详细磁盘使用
docker system df -v

9.6 网络管理

bash 复制代码
# 查看所有网络
docker network ls

# 查看网络详情
docker network inspect host

# 查看容器网络
docker inspect -f '{{.NetworkSettings.Networks}}' abnormal-monitoring

# 查看容器 IP(bridge 模式)
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' abnormal-monitoring

十、故障排查指南

10.1 容器无法启动

症状

bash 复制代码
docker ps -a
# STATUS 显示 Exited (1) 或 Exited (137)

排查步骤

  1. 查看日志
bash 复制代码
docker logs abnormal-monitoring
  1. 常见原因及解决方案
错误信息 原因 解决方案
Error: Could not find or load main class jar 包损坏或路径错误 检查 jar 包完整性
Address already in use 端口被占用 检查端口占用: `netstat -tlnp
Cannot connect to database 数据库连接失败 检查数据库配置和网络
OOMKilled 内存溢出 增加容器内存限制
Permission denied 权限问题 检查挂载目录权限

10.2 应用启动慢或卡住

排查步骤

bash 复制代码
# 1. 查看实时日志
docker logs -f abnormal-monitoring

# 2. 进入容器检查进程
docker exec -it abnormal-monitoring /bin/bash
ps aux | grep java
top

# 3. 检查资源使用
docker stats abnormal-monitoring

# 4. 检查磁盘空间
df -h
docker exec abnormal-monitoring df -h

# 5. 检查网络连接
docker exec abnormal-monitoring ping -c 3 127.0.0.1

10.3 端口无法访问

排查步骤

bash 复制代码
# 1. 检查容器是否运行
docker ps | grep abnormal-monitoring

# 2. 检查端口监听(host 模式)
netstat -tlnp | grep 8089
ss -tlnp | grep 8089

# 3. 检查防火墙
firewall-cmd --list-ports
firewall-cmd --add-port=8089/tcp --permanent
firewall-cmd --reload

# 4. 检查 SELinux
getenforce
setenforce 0  # 临时关闭

# 5. 测试本地访问
curl http://localhost:8089

# 6. 检查应用日志
docker logs abnormal-monitoring | grep -i error

10.4 容器频繁重启

排查步骤

bash 复制代码
# 1. 查看容器重启次数
docker inspect abnormal-monitoring | grep RestartCount

# 2. 查看退出代码
docker ps -a | grep abnormal-monitoring

# 3. 查看日志找出崩溃原因
docker logs --tail 200 abnormal-monitoring

# 4. 禁用自动重启进行调试
docker update --restart=no abnormal-monitoring

# 5. 检查系统资源
free -h
df -h

10.5 数据卷挂载问题

排查步骤

bash 复制代码
# 1. 检查挂载配置
docker inspect abnormal-monitoring | grep -A 10 Mounts

# 2. 检查宿主机目录权限
ls -ld /home/rkg/templateFile

# 3. 检查容器内目录
docker exec abnormal-monitoring ls -la /home/rkg/templateFile

# 4. 修复权限
chmod 755 /home/rkg/templateFile
chown -R root:root /home/rkg/templateFile

# 5. 测试读写
docker exec abnormal-monitoring touch /home/rkg/templateFile/test.txt

10.6 镜像构建失败

常见错误及解决

  1. Dockerfile 解析错误
bash 复制代码
# 错误: dockerfile parse error on line 1: unknown instruction: cd
# 解决: 删除 Dockerfile 中的 shell 命令
rm Dockerfile
# 重新创建正确的 Dockerfile
  1. 找不到 jar 包
bash 复制代码
# 错误: COPY failed: file not found
# 解决: 检查文件名
ls -lh /home/smart-brain/*.jar
# 修改 Dockerfile 中的 COPY 指令或重命名文件
  1. 基础镜像拉取失败
bash 复制代码
# 错误: Error response from daemon: pull access denied
# 解决: 手动拉取镜像
docker pull openjdk:17.0.2
  1. 磁盘空间不足
bash 复制代码
# 错误: no space left on device
# 解决: 清理 Docker 资源
docker system prune -a

10.7 网络连接问题

排查步骤

bash 复制代码
# 1. 检查网络模式
docker inspect abnormal-monitoring | grep NetworkMode

# 2. 测试容器网络(进入容器)
docker exec -it abnormal-monitoring /bin/bash

# 测试外网连接
ping -c 3 8.8.8.8

# 测试 DNS
nslookup baidu.com

# 测试 Nacos
curl http://127.0.0.1:8848/nacos/v1/console/health/readiness

# 测试 Redis
redis-cli -h 127.0.0.1 -p 6379 ping

exit

# 3. 检查宿主机网络
ping -c 3 127.0.0.1
netstat -tlnp | grep 8848

10.8 性能问题

排查步骤

bash 复制代码
# 1. 查看容器资源使用
docker stats abnormal-monitoring

# 2. 查看 JVM 内存
docker exec abnormal-monitoring jmap -heap <PID>

# 3. 查看线程数
docker exec abnormal-monitoring jstack <PID> | grep "java.lang.Thread.State" | wc -l

# 4. 导出堆转储(OOM 时)
docker exec abnormal-monitoring jmap -dump:format=b,file=/tmp/heap.hprof <PID>

# 5. 增加容器资源限制
docker update --memory="4g" --cpus="2" abnormal-monitoring

10.9 日志排查技巧

bash 复制代码
# 1. 查找错误日志
docker logs abnormal-monitoring | grep -i error

# 2. 查找异常日志
docker logs abnormal-monitoring | grep -i exception

# 3. 查找启动日志
docker logs abnormal-monitoring | grep -i "started"

# 4. 统计错误数量
docker logs abnormal-monitoring | grep -c "ERROR"

# 5. 过滤特定时间段
docker logs --since "2024-12-10T10:00:00" --until "2024-12-10T11:00:00" abnormal-monitoring

# 6. 导出完整日志进行分析
docker logs abnormal-monitoring > /tmp/app-full.log 2>&1

10.10 应急处理流程

快速恢复服务

bash 复制代码
#!/bin/bash
# 应急恢复脚本

CONTAINER_NAME="abnormal-monitoring"

echo "=== 应急恢复流程 ==="

# 1. 重启容器
echo "1. 尝试重启容器..."
docker restart $CONTAINER_NAME
sleep 10

# 2. 检查状态
if docker ps | grep -q $CONTAINER_NAME; then
    echo "✓ 容器重启成功"
    exit 0
fi

# 3. 查看日志
echo "2. 容器重启失败,查看日志..."
docker logs --tail 50 $CONTAINER_NAME

# 4. 删除并重新创建
echo "3. 删除容器并重新创建..."
docker stop $CONTAINER_NAME
docker rm $CONTAINER_NAME

docker run -dit \
  --name $CONTAINER_NAME \
  --network host \
  --restart=unless-stopped \
  -v /home/rkg/templateFile:/home/rkg/templateFile \
  abnormal-monitoring:v0.0.1

sleep 10

# 5. 最终检查
if docker ps | grep -q $CONTAINER_NAME; then
    echo "✓ 服务恢复成功"
else
    echo "✗ 服务恢复失败,请手动排查"
    exit 1
fi

附录

A. 完整示例配置文件

application.yml(host 网络模式)

yaml 复制代码
server:
  port: 8089

spring:
  application:
    name: abnormal-monitoring
  
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public
  
  datasource:
    url: jdbc:postgresql://127.0.0.1:54321/smart_brain
    username: SYSTEM
    password: 123456
  
  redis:
    host: 127.0.0.1
    port: 6379

B. 检查清单

部署前检查:

  • Docker 已安装并运行
  • jar 包已上传
  • Dockerfile 已创建
  • 挂载目录已创建
  • 端口未被占用
  • 磁盘空间充足

部署后检查:

  • 容器运行正常
  • 端口正常监听
  • 应用日志正常
  • 服务注册成功(如使用 Nacos)
  • 接口可正常访问

C. 常用链接


文档版本 : v1.0
最后更新 : 2025年12月9日
适用范围: Spring Boot + Docker + CentOS/RHEL

相关推荐
ArabySide2 小时前
【Spring Boot】用Spring AOP优雅实现横切逻辑复用
java·spring boot·后端
南山乐只2 小时前
Spring Boot 2.x => 3.x 升级指南
java·spring boot·后端
Q_Q19632884752 小时前
python+django/flask+vue的智能房价分析与预测系统
spring boot·python·django·flask·node.js·php
汝生淮南吾在北2 小时前
SpringBoot3+Vue3新闻动态网站
前端·javascript·vue.js·spring boot·毕业设计·毕设
一只游鱼3 小时前
Docker部署微服务
docker
Q_Q5110082853 小时前
python+django/flask+vue的购物管理系统
spring boot·python·django·flask·node.js
Q_Q5110082853 小时前
python+springboot+django/flask基于数据挖掘的高考志愿推荐系统
spring boot·python·django·flask·node.js·php
Q_Q5110082853 小时前
python+springboot+django/flask基于用户评论主题挖掘的旅游景点推荐系统
spring boot·python·django·flask·node.js
JavaBoy_XJ3 小时前
Mysql在 Spring Boot 项目中的完整配置指南
数据库·spring boot·mysql·mysql配置