#!/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 "$@"