From dec7582f982c9f8fd52d2608d1764e8228921e8f Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 21 Jul 2026 13:48:08 +0800 Subject: [PATCH] =?UTF-8?q?perf(ci):=20Dockerfile=E4=BC=98=E5=8C=96=20-=20?= =?UTF-8?q?cache=20mount=E5=8A=A0=E9=80=9F=E4=BE=9D=E8=B5=96=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=20+=20API=E5=A4=9A=E9=98=B6=E6=AE=B5=E7=98=A6?= =?UTF-8?q?=E8=BA=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit API Dockerfile: - 改为多阶段构建(builder+runtime),编译依赖留在builder - runtime只装libpq5运行时库,镜像体积减小 - 加pip cache mount,加速重复构建的依赖下载 - strip .so调试符号 + 清理pyc,进一步瘦身 Worker Dockerfile: - 加pip cache mount(3处pip install都加) - ffmpeg下载加cache mount,避免每次重新下载几十MB - 原有的多阶段+瘦身逻辑保持不变 --- infra/docker/api.Dockerfile | 73 +++++++++++++++++++++++++--------- infra/docker/worker.Dockerfile | 26 +++++++----- 2 files changed, 72 insertions(+), 27 deletions(-) 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 -- 2.54.0