#!/usr/bin/env python3 """ 应用打包脚本 - 将Python应用打包为可执行文件 """ import os import sys import shutil import subprocess from pathlib import Path def check_dependencies(): """检查必要的依赖""" try: import PyInstaller print("OK PyInstaller 已安装") except ImportError: print("正在安装 PyInstaller...") subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller"]) print("OK PyInstaller 安装完成") def create_spec_file(): """创建 PyInstaller spec 文件""" spec_content = ''' # -*- mode: python ; coding: utf-8 -*- block_cipher = None a = Analysis( ['main.py'], pathex=[], binaries=[], datas=[ ('app', 'app'), ('uploads', 'uploads'), ('logs', 'logs'), ], hiddenimports=[ 'uvicorn', 'fastapi', 'sqlalchemy', 'pymysql', 'pydantic', 'pydantic_settings', 'redis', 'passlib', 'python_jose', 'uvicorn.protocols.http.httptools_impl', ], hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, ) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='cloud-drive-server', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, icon=None ) ''' with open('cloud-drive-server.spec', 'w', encoding='utf-8') as f: f.write(spec_content) print("OK 创建了 cloud-drive-server.spec 文件") def build_executable(): """构建可执行文件""" print("开始构建可执行文件...") try: # 使用 PyInstaller 构建 result = subprocess.run([ sys.executable, '-m', 'PyInstaller', '--clean', '--noconfirm', 'cloud-drive-server.spec' ], capture_output=True, text=True) if result.returncode == 0: print("OK 可执行文件构建成功") print("输出目录: dist/") return True else: print("ERROR 构建失败:") print(result.stdout) print(result.stderr) return False except Exception as e: print(f"ERROR 构建过程中出现错误: {e}") return False def create_dockerfile_for_executable(): """为可执行文件创建最小化的 Dockerfile""" dockerfile_content = '''# 最小化运行环境 - 使用可执行文件 FROM alpine:latest # 安装运行时依赖 RUN apk add --no-cache \\ curl \\ tzdata \\ ca-certificates \\ && rm -rf /var/cache/apk/* # 设置时区 ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # 创建应用用户 RUN adduser -D -s /bin/sh app # 设置工作目录 WORKDIR /app # 复制可执行文件 COPY dist/cloud-drive-server /app/cloud-drive-server # 创建必要的目录 RUN mkdir -p /app/uploads /app/logs \\ && chown -R app:app /app # 切换到非root用户 USER app # 暴露端口 EXPOSE 8002 # 健康检查 HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \\ CMD curl -f http://localhost:8002/api/v1/health || exit 1 # 启动命令 CMD ["./cloud-drive-server"] ''' with open('Dockerfile.executable', 'w', encoding='utf-8') as f: f.write(dockerfile_content) print("OK 创建了 Dockerfile.executable 文件") def main(): """主函数""" print("=== 云盘应用打包工具 ===") print("正在将应用打包为Docker镜像...") # 检查当前目录 if not Path('main.py').exists(): print("ERROR 错误: 在当前目录未找到 main.py 文件") print("请在 backend 目录中运行此脚本") return False # 检查依赖 check_dependencies() # 创建 spec 文件 create_spec_file() # 构建可执行文件 if not build_executable(): return False # 创建可执行文件的 Dockerfile create_dockerfile_for_executable() print("\n=== 打包完成 ===") print("OK 应用已成功打包") print("OK 可执行文件位于: dist/cloud-drive-server") print("OK Dockerfile: Dockerfile.executable") print("\n下一步命令:") print(" docker build -f Dockerfile.executable -t cloud-drive-backend:latest .") print(" docker run -d -p 8002:8002 --name cloud-drive-backend cloud-drive-backend:latest") return True if __name__ == "__main__": success = main() sys.exit(0 if success else 1)