Files
full-stack-doc/backend/build-docker-fixed.sh
2025-10-14 20:05:29 +08:00

369 lines
9.9 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# 云盘应用 Docker 构建和部署脚本 (修复权限问题版本)
# 用于构建生产环境的 Docker 镜像并部署到 Linux 环境
set -e
# 配置变量
APP_NAME="cloud-drive-backend"
IMAGE_NAME="${APP_NAME}:latest"
CONTAINER_NAME="${APP_NAME}"
PORT="8002"
USE_SUDO=false
# Docker命令包装函数
docker_cmd() {
if [ "$USE_SUDO" = true ]; then
sudo docker "$@"
else
docker "$@"
fi
}
# Docker Compose命令包装函数
docker_compose_cmd() {
if [ "$USE_SUDO" = true ]; then
sudo docker-compose "$@"
else
docker-compose "$@"
fi
}
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查 Docker 是否安装
check_docker() {
if ! command -v docker &> /dev/null; then
log_error "Docker 未安装,请先安装 Docker"
exit 1
fi
# 检查Docker权限
if ! docker info &> /dev/null; then
log_warning "Docker权限不足尝试修复..."
# 检查当前用户是否在docker组中
if ! groups $(whoami) | grep -q docker; then
log_warning "当前用户不在docker组中"
# 尝试将用户添加到docker组
if command -v sudo &> /dev/null; then
log_info "尝试将用户添加到docker组需要sudo权限..."
sudo usermod -aG docker $(whoami) 2>/dev/null || {
log_warning "无法自动添加用户到docker组"
log_info "请手动执行: sudo usermod -aG docker $(whoami)"
log_info "然后重新登录或执行: newgrp docker"
}
else
log_error "sudo命令不可用无法修复Docker权限"
fi
fi
# 尝试使用sudo运行docker
if command -v sudo &> /dev/null && sudo docker info &> /dev/null; then
log_info "检测到可以使用sudo运行Docker"
USE_SUDO=true
else
log_error "Docker权限不足且无法修复"
log_info "解决方案:"
log_info "1. 将用户添加到docker组: sudo usermod -aG docker $(whoami)"
log_info "2. 重新登录或执行: newgrp docker"
log_info "3. 或使用sudo运行此脚本"
exit 1
fi
fi
log_success "Docker 已安装并可访问"
}
# 检查 Docker Compose 是否安装
check_docker_compose() {
if ! command -v docker-compose &> /dev/null; then
log_error "Docker Compose 未安装,请先安装 Docker Compose"
exit 1
fi
log_success "Docker Compose 已安装"
}
# 停止并删除现有容器
stop_existing_container() {
if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then
log_warning "停止现有容器 ${CONTAINER_NAME}"
docker_cmd stop ${CONTAINER_NAME}
fi
if docker_cmd ps -aq -f name=${CONTAINER_NAME} | grep -q .; then
log_warning "删除现有容器 ${CONTAINER_NAME}"
docker_cmd rm ${CONTAINER_NAME}
fi
}
# 构建镜像
build_image() {
log_info "开始构建 Docker 镜像..."
docker_cmd build -t ${IMAGE_NAME} .
if [ $? -eq 0 ]; then
log_success "镜像构建成功: ${IMAGE_NAME}"
else
log_error "镜像构建失败"
exit 1
fi
}
# 运行容器
run_container() {
log_info "启动容器..."
# 创建必要的目录
mkdir -p uploads logs
docker_cmd run -d \
--name ${CONTAINER_NAME} \
--restart unless-stopped \
-p ${PORT}:${PORT} \
-v $(pwd)/uploads:/app/uploads \
-v $(pwd)/logs:/app/logs \
-e ENVIRONMENT=production \
-e TZ=Asia/Shanghai \
${IMAGE_NAME}
if [ $? -eq 0 ]; then
log_success "容器启动成功: ${CONTAINER_NAME}"
else
log_error "容器启动失败"
exit 1
fi
}
# 检查容器状态
check_container() {
log_info "检查容器状态..."
sleep 5
if docker_cmd ps | grep -q ${CONTAINER_NAME}; then
log_success "容器运行正常"
# 显示容器日志
log_info "容器日志:"
docker_cmd logs ${CONTAINER_NAME}
# 测试健康检查
log_info "测试健康检查..."
sleep 10
if curl -f http://localhost:${PORT}/api/v1/health &> /dev/null; then
log_success "健康检查通过!"
else
log_warning "健康检查失败,但容器仍在运行"
fi
else
log_error "容器未正常运行"
log_error "容器日志:"
docker_cmd logs ${CONTAINER_NAME}
exit 1
fi
}
# 使用 Docker Compose 部署
deploy_with_compose() {
log_info "使用 Docker Compose 部署..."
# 创建 .env 文件(如果不存在)
if [ ! -f .env ]; then
log_warning "创建 .env 文件,请根据实际情况修改配置"
cat > .env << EOF
# 数据库配置
DATABASE_URL=mysql://username:password@mysql:3306/mytest_db
MYSQL_ROOT_PASSWORD=rootpassword
MYSQL_DATABASE=mytest_db
MYSQL_USER=username
MYSQL_PASSWORD=password
# Redis 配置
REDIS_URL=redis://redis:6379/0
# 应用配置
SECRET_KEY=your-production-secret-key
CORS_ORIGINS=http://localhost:3003,https://yourdomain.com
ENVIRONMENT=production
EOF
log_warning "请编辑 .env 文件设置正确的配置"
fi
docker_compose_cmd down
docker_compose_cmd up -d --build
if [ $? -eq 0 ]; then
log_success "Docker Compose 部署成功"
log_info "等待服务启动..."
sleep 15
if curl -f http://localhost:${PORT}/api/v1/health &> /dev/null; then
log_success "应用启动成功!"
log_info "服务地址: http://localhost:${PORT}"
log_info "API文档: http://localhost:${PORT}/docs"
log_info "健康检查: http://localhost:${PORT}/api/v1/health"
else
log_warning "应用启动可能有问题,请检查日志"
log_info "查看日志命令: docker-compose logs -f"
docker_compose_cmd logs --tail=20
fi
else
log_error "Docker Compose 部署失败"
exit 1
fi
}
# 清理镜像和容器
cleanup() {
log_info "清理旧的镜像和容器..."
# 停止并删除容器
stop_existing_container
# 删除镜像
if docker_cmd images -q ${IMAGE_NAME} | grep -q .; then
log_warning "删除旧镜像: ${IMAGE_NAME}"
docker_cmd rmi ${IMAGE_NAME} 2>/dev/null || true
fi
# 清理未使用的镜像和容器
log_info "清理未使用的 Docker 资源..."
docker_cmd system prune -f
log_success "清理完成"
}
# 显示帮助信息
show_help() {
echo "云盘应用 Docker 部署脚本 (权限修复版)"
echo ""
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " build - 仅构建镜像"
echo " run - 仅运行容器(需要先构建镜像)"
echo " compose - 使用 Docker Compose 部署"
echo " stop - 停止容器"
echo " restart - 重启容器"
echo " logs - 查看容器日志"
echo " cleanup - 清理镜像和容器"
echo " status - 查看容器状态"
echo " help - 显示此帮助信息"
echo ""
echo "默认行为: 构建镜像并运行容器"
echo ""
echo "权限修复功能:"
echo "- 自动检测Docker权限"
echo "- 尝试自动修复权限问题"
echo "- 支持sudo模式运行Docker"
}
# 主函数
main() {
case "${1:-}" in
"build")
check_docker
build_image
;;
"run")
check_docker
stop_existing_container
run_container
check_container
;;
"compose")
check_docker
check_docker_compose
deploy_with_compose
;;
"stop")
check_docker
if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then
docker_cmd stop ${CONTAINER_NAME}
log_success "容器已停止"
else
log_warning "容器未运行"
fi
;;
"restart")
check_docker
if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then
docker_cmd restart ${CONTAINER_NAME}
log_success "容器已重启"
sleep 5
check_container
else
log_warning "容器未运行,尝试启动..."
stop_existing_container
build_image
run_container
check_container
fi
;;
"logs")
check_docker
if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then
docker_cmd logs -f ${CONTAINER_NAME}
else
log_warning "容器未运行"
fi
;;
"cleanup")
check_docker
cleanup
;;
"status")
check_docker
if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then
log_success "容器正在运行"
docker_cmd ps | grep ${CONTAINER_NAME}
else
log_warning "容器未运行"
fi
;;
"help"|"-h"|"--help")
show_help
;;
"")
log_info "开始构建和部署云盘应用..."
check_docker
stop_existing_container
build_image
run_container
check_container
log_success "部署完成!应用正在运行中"
;;
*)
log_error "未知选项: $1"
show_help
exit 1
;;
esac
}
# 执行主函数
main "$@"