diff --git a/infra/docker/api.Dockerfile b/infra/docker/api.Dockerfile index 64d2dde99..bf3b58a66 100755 --- a/infra/docker/api.Dockerfile +++ b/infra/docker/api.Dockerfile @@ -1,33 +1,69 @@ # ============================================================ -# API Dockerfile - 专门用于 FastAPI 应用 -# 优化:依赖分层缓存 + 多阶段构建基础层 +# API Dockerfile - FastAPI 应用 +# 优化:多阶段构建 + pip cache mount + 依赖分层缓存 # ============================================================ -# 基础镜像:Python 3.12 -FROM git.xiaoxiajianji.com/xiaoxia/base/python:3.12-slim +# ==================== Builder 阶段 ==================== +FROM git.xiaoxiajianji.com/xiaoxia/base/python:3.12-slim AS builder + +# 使用阿里云镜像加速 +RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || \ + sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list 2>/dev/null || true + +# 安装编译依赖(仅 builder 需要) +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc \ + libpq-dev \ + && rm -rf /var/lib/apt/lists/* + +# 创建虚拟环境 +RUN python -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" + +WORKDIR /tmp + +# ---- 依赖分层:基础依赖(变化少,缓存命中率高)---- +COPY requirements-base.txt /tmp/requirements-base.txt + +RUN --mount=type=cache,target=/root/.cache/pip,sharing=locked \ + pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com \ + -r /tmp/requirements-base.txt \ + && rm /tmp/requirements-base.txt + +# ---- 依赖分层:业务依赖(变化频繁)---- +COPY requirements.txt /tmp/requirements.txt + +RUN --mount=type=cache,target=/root/.cache/pip,sharing=locked \ + pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com \ + -r /tmp/requirements.txt \ + && rm /tmp/requirements.txt + +# ---- Python 依赖瘦身 ---- +RUN find /opt/venv -name "*.so" -type f -exec strip --strip-all {} \; 2>/dev/null || true +RUN find /opt/venv -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null; \ + find /opt/venv -name "*.pyc" -delete 2>/dev/null || true + +# ==================== Runtime 阶段 ==================== +FROM git.xiaoxiajianji.com/xiaoxia/base/python:3.12-slim AS runtime # 构建参数:版本号(CI 传入 commit hash) ARG APP_VERSION=dev # 使用阿里云镜像加速 -RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list 2>/dev/null || true +RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || \ + sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list 2>/dev/null || true -# 安装系统依赖 -RUN apt-get update && apt-get install -y --no-install-recommends libpq-dev && rm -rf /var/lib/apt/lists/* +# 只装运行时需要的库(libpq5 是 psycopg2 运行时依赖) +RUN apt-get update && apt-get install -y --no-install-recommends \ + libpq5 \ + && rm -rf /var/lib/apt/lists/* + +# 从 builder 复制虚拟环境 +COPY --from=builder /opt/venv /opt/venv # 设置工作目录 WORKDIR /app -# ---- 依赖分层:基础依赖(变化少,缓存命中率高)---- -COPY requirements-base.txt /tmp/requirements-base.txt - -RUN python -m venv /opt/venv && /opt/venv/bin/pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com -r /tmp/requirements-base.txt && rm /tmp/requirements-base.txt - -# ---- 依赖分层:业务依赖(变化频繁)---- -COPY requirements.txt /tmp/requirements.txt - -RUN /opt/venv/bin/pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com -r /tmp/requirements.txt && rm /tmp/requirements.txt - # 复制应用代码 COPY apps/api/ /app/apps/api/ COPY packages/ /app/packages/ @@ -43,7 +79,8 @@ ENV PYTHONUNBUFFERED=1 ENV APP_VERSION=$APP_VERSION # 健康检查 -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)" +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)" # API 入口点 WORKDIR /app/apps/api diff --git a/infra/docker/worker.Dockerfile b/infra/docker/worker.Dockerfile index 32766988d..26f20d807 100755 --- a/infra/docker/worker.Dockerfile +++ b/infra/docker/worker.Dockerfile @@ -1,9 +1,11 @@ # ============================================================ -# Worker Dockerfile - 优化版(多阶段构建 + 镜像瘦身) +# Worker Dockerfile - 优化版(多阶段构建 + 镜像瘦身 + cache mount加速) # 优化项: # 1. 多阶段构建:builder 阶段安装编译依赖,runtime 阶段只保留运行时 # 2. ffmpeg 静态编译替换:从 apt 安装(457MB) 改为静态二进制(~80MB) # 3. Python 依赖瘦身:strip .so 调试符号 + 清理测试文件 + 清理缓存 +# 4. pip cache mount:加速依赖下载(跨构建共享pip wheel缓存) +# 5. ffmpeg cache mount:避免每次重新下载静态编译包 # ============================================================ # ==================== Builder 阶段 ==================== @@ -23,11 +25,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ && rm -rf /var/lib/apt/lists/* -# ---- 下载静态编译 ffmpeg ---- -# 使用 johnvansickle.com 的静态编译版本(业界标准) -RUN cd /tmp \ - && wget -q https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz \ - && tar xf ffmpeg-release-amd64-static.tar.xz \ +# ---- 下载静态编译 ffmpeg(带缓存,避免每次重新下载)---- +RUN --mount=type=cache,target=/tmp/ffmpeg-cache,sharing=locked \ + cd /tmp \ + && if [ ! -f /tmp/ffmpeg-cache/ffmpeg-release-amd64-static.tar.xz ]; then \ + wget -q -O /tmp/ffmpeg-cache/ffmpeg-release-amd64-static.tar.xz \ + https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz; \ + fi \ + && tar xf /tmp/ffmpeg-cache/ffmpeg-release-amd64-static.tar.xz \ && cp ffmpeg-*-amd64-static/ffmpeg /usr/local/bin/ffmpeg \ && cp ffmpeg-*-amd64-static/ffprobe /usr/local/bin/ffprobe \ && chmod +x /usr/local/bin/ffmpeg /usr/local/bin/ffprobe \ @@ -42,19 +47,22 @@ ENV PATH="/opt/venv/bin:$PATH" # 基础依赖 COPY requirements-base.txt /tmp/requirements-base.txt -RUN pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com \ +RUN --mount=type=cache,target=/root/.cache/pip,sharing=locked \ + pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com \ -r /tmp/requirements-base.txt \ && rm /tmp/requirements-base.txt # Worker 专属大包 COPY requirements-worker.txt /tmp/requirements-worker.txt -RUN pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com \ +RUN --mount=type=cache,target=/root/.cache/pip,sharing=locked \ + pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com \ -r /tmp/requirements-worker.txt \ && rm /tmp/requirements-worker.txt # 业务依赖 COPY requirements.txt /tmp/requirements.txt -RUN pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com \ +RUN --mount=type=cache,target=/root/.cache/pip,sharing=locked \ + pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com \ -r /tmp/requirements.txt \ && rm /tmp/requirements.txt