diff --git a/infra/docker/api.Dockerfile b/infra/docker/api.Dockerfile index e3f56e3d6..33d99d02c 100644 --- a/infra/docker/api.Dockerfile +++ b/infra/docker/api.Dockerfile @@ -1,16 +1,64 @@ -FROM python:3.12-slim +# ============================================================================= +# 小虾 SaaS API 多阶段构建 +# ============================================================================= +# Stage 1: Builder - 安装依赖 +FROM python:3.12-slim AS builder + WORKDIR /app -ENV PYTHONPATH=/app -ENV PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/ -ENV PIP_TRUSTED_HOST=mirrors.aliyun.com -COPY requirements.txt ./ -RUN python -m pip install --upgrade pip setuptools wheel && \ - pip install --no-cache-dir --default-timeout=120 --retries 10 -r requirements.txt -COPY apps/api /app/apps/api -COPY packages /app/packages -COPY scripts /app/scripts -COPY alembic /app/alembic -COPY alembic.ini /app/alembic.ini + +# 安装构建依赖 +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc \ + libpq-dev \ + && rm -rf /var/lib/apt/lists/* + +# 复制依赖文件并安装 +COPY requirements.txt . +RUN pip install --no-cache-dir --user --upgrade pip setuptools wheel && \ + pip install --no-cache-dir --user -r requirements.txt + +# ============================================================================= +# Stage 2: Runtime - 运行镜像 +FROM python:3.12-slim AS runtime + +# 安全:使用非 root 用户 +RUN groupadd --gid 1000 appgroup && \ + useradd --uid 1000 --gid appgroup --shell /bin/bash --create-home appuser + +WORKDIR /app + +# 设置环境变量 +ENV PYTHONPATH=/app \ + PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 \ + PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/ \ + PIP_TRUSTED_HOST=mirrors.aliyun.com + +# 安装运行时依赖(排除构建工具) +RUN apt-get update && apt-get install -y --no-install-recommends \ + libpq5 \ + && rm -rf /var/lib/apt/lists/* + +# 从 builder 阶段复制已安装的包 +COPY --from=builder /root/.local /home/appuser/.local +COPY --from=builder /app /app + +# 设置 PATH 包含用户本地 bin +ENV PATH=/home/appuser/.local/bin:$PATH + +# 复制应用代码 +COPY --chown=appuser:appgroup apps/api /app/apps/api +COPY --chown=appuser:appgroup packages /app/packages +COPY --chown=appuser:appgroup scripts /app/scripts +COPY --chown=appuser:appgroup alembic /app/alembic +COPY --chown=appuser:appgroup alembic.ini /app/alembic.ini + +# 切换到非 root 用户 +USER appuser + WORKDIR /app/apps/api + EXPOSE 8000 + CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]