| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- # 第一阶段:构建前端应用
- 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"]
|