# 第一阶段:构建前端应用 FROM docker.1ms.run/node:22-alpine3.21 AS frontend-builder # 设置工作目录 WORKDIR /app/frontend # 设置npm镜像源为阿里源 RUN npm config set registry https://registry.npmmirror.com # 创建.npmrc文件确保使用正确的镜像源 RUN echo "registry=https://registry.npmmirror.com" > .npmrc # 先复制package.json和package-lock.json COPY frontend/package.json frontend/package-lock.json* ./ # 安装依赖时使用更好的缓存策略和更少的日志输出 RUN npm ci --legacy-peer-deps --no-fund --no-audit --quiet # 复制所有前端文件(这行之后的代码变更会重新触发构建) COPY frontend/ . # 显示文件结构 RUN echo "=== 文件结构检查 ===" && ls -la && ls -la public/ # 构建前端应用 RUN echo "=== 开始构建前端应用 ===" && npm run build # 检查构建产物 RUN echo "=== 构建产物检查 ===" && ls -la dist/ && \ if [ -z "$(ls -A dist)" ]; then \ echo "错误: dist目录为空" && exit 1; \ else \ echo "构建成功,dist目录不为空"; \ fi # 第二阶段:构建Python后端 FROM docker.1ms.run/python:3.9-slim # 设置工作目录 WORKDIR /app/backend # 设置pip镜像源为阿里源 RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ # 强制使用阿里源,完全清除所有其他源的引用 # 删除所有可能的源文件,使用更彻底的方式 RUN rm -f /etc/apt/sources.list /etc/apt/sources.list.d/*.list && \ mkdir -p /etc/apt/sources.list.d && \ rm -f /etc/apt/sources.list.d/*.list # 只创建包含阿里源的源文件,使用安全的写法确保文件存在 RUN echo 'deb http://mirrors.aliyun.com/debian/ trixie main contrib non-free' > /etc/apt/sources.list && \ echo 'deb-src http://mirrors.aliyun.com/debian/ trixie main contrib non-free' >> /etc/apt/sources.list && \ echo 'deb http://mirrors.aliyun.com/debian/ trixie-updates main contrib non-free' >> /etc/apt/sources.list && \ echo 'deb-src http://mirrors.aliyun.com/debian/ trixie-updates main contrib non-free' >> /etc/apt/sources.list && \ echo 'deb http://mirrors.aliyun.com/debian-security/ trixie-security main contrib non-free' >> /etc/apt/sources.list && \ echo 'deb-src http://mirrors.aliyun.com/debian-security/ trixie-security main contrib non-free' >> /etc/apt/sources.list # 验证源文件内容 RUN echo "=== 验证源文件内容 ===" && cat /etc/apt/sources.list # 确保没有其他源文件存在 RUN echo "=== 检查是否存在其他源文件 ===" && ls -la /etc/apt/ /etc/apt/sources.list.d/ 2>/dev/null || echo "No sources.list.d directory" # 使用Python内置的http客户端进行健康检查,避免额外依赖 # 清理并重建apt缓存,仅使用清华源,添加更多参数确保不使用其他源 RUN echo "=== 清理并重建apt缓存 ===" && \ rm -rf /var/lib/apt/lists/* && \ apt-get clean && \ # 设置严格的apt配置,确保只使用指定的源 apt-config dump && \ # 执行update并严格只使用清华源 apt-get update -o Acquire::ForceIPv4=true -o Acquire::AllowInsecureRepositories=true -o Dir::Etc::sourcelist="/etc/apt/sources.list" -o Dir::Etc::sourceparts="" -o APT::Get::List-Cleanup="0" && \ # 安装必要的依赖 apt-get install -y --no-install-recommends \ gcc \ python3-dev \ libffi-dev \ && rm -rf /var/lib/apt/lists/* # 复制Python依赖文件 COPY backend/requirements.txt . # 安装Python依赖 RUN pip install --no-cache-dir -r requirements.txt # 创建静态文件目录 RUN mkdir -p /app/backend/static # 复制前端构建产物到后端静态文件夹 COPY --from=frontend-builder /app/frontend/dist /app/backend/static # 使用更灵活的方式修改index.html中的脚本引用路径,不再硬编码文件名 RUN echo "=== 修改index.html脚本引用 ===" && \ # 查找实际的main.js文件 MAIN_JS_FILE=$(find /app/backend/static/assets -name "main-*.js" | head -1) && \ MAIN_JS_BASENAME=$(basename "$MAIN_JS_FILE") && \ echo "找到main.js文件: $MAIN_JS_BASENAME" && \ # 替换index.html中的引用路径 sed -i "s|/src/main.js|/assets/$MAIN_JS_BASENAME|g" /app/backend/static/index.html # 检查静态文件目录和修改后的index.html RUN echo "=== 静态文件目录检查 ===" && ls -la /app/backend/static/ && ls -la /app/backend/static/assets/ && echo "=== index.html内容 ===" && cat /app/backend/static/index.html # 复制后端源代码 COPY backend/ . # 设置环境变量 ENV FLASK_APP=app.py ENV FLASK_ENV=production ENV TZ=Asia/Shanghai # 添加健康检查(使用Python内置的http.client模块) HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \ CMD python -c "import http.client; conn = http.client.HTTPConnection('localhost', 5001); conn.request('GET', '/api/health'); res = conn.getresponse(); exit(0 if res.status < 400 else 1)" # 使用非root用户运行应用以提高安全性 RUN groupadd -r appuser && useradd -r -g appuser appuser RUN chown -R appuser:appuser /app/backend USER appuser # 暴露应用端口 EXPOSE 5001 # 简化启动命令 - 确保端口统一为5001 CMD ["python", "-m", "flask", "run", "--host=0.0.0.0", "--port=5001"]