# ============================================================
# Dockerfile：项目镜像（多阶段构建）
# 基础镜像：python-base:3.12.8（RockyLinux 8 + Python 3.12.8 + mariadb-connector-c）
#
# 设计要点
#   - builder 只编译依赖，装到 /opt/deps，不碰基础镜像的 Python 目录
#   - runtime 继承基础镜像的 Python，只把依赖的 site-packages COPY 过来
#   - MySQL 运行库（mariadb-connector-c）由基础镜像预置，runtime 无需重复安装
#   - 用 COPY --chown 指定属主，避免额外的 chown 层
#   - 源码 COPY 放在依赖之后，保护依赖层缓存
#
# 构建参数
#   VAR_BASE_IMAGE            基础镜像
#   VAR_PYTHON_PREFIX         Python 安装前缀（与基础镜像一致）
#   VAR_PYTHON_SHORT_VERSION  Python 主次版本号，用于 site-packages 路径
#   VAR_PYFILE_PATH           项目源码目录
#   VAR_PROFILES              应用 profile（dev / prod）
#   VAR_PORT                  应用监听端口
#   VAR_PYFILE                入口文件名（不含 .py）
# ============================================================


# ------------------------------------------------------------
# 全局构建参数
#   在 FROM 之前声明，可供后续各阶段引用
# ------------------------------------------------------------
ARG VAR_BASE_IMAGE
ARG VAR_PYTHON_PREFIX=/usr/local/python3.12.8
ARG VAR_PYTHON_SHORT_VERSION=3.12


# ============================================================
# 阶段一：builder —— 编译并安装项目依赖
# ============================================================
FROM ${VAR_BASE_IMAGE} AS builder

# 阶段内重新声明，否则读不到全局 ARG
# Docker 规则：全局 ARG 只在 FROM 行可见，阶段内使用必须重新声明
ARG VAR_PYTHON_PREFIX
ARG VAR_PYTHON_SHORT_VERSION
ARG VAR_PYFILE_PATH

# 基础镜像末尾是 esxi 用户；dnf/pip 需要写系统目录和 /opt/deps，
# 所以这里仍需 root
USER root

LABEL MAINTAINER="djangoadmin@126.com"

# 编译阶段环境变量
#   PYTHONUNBUFFERED=1              日志实时输出
#   PYTHONDONTWRITEBYTECODE=1       不生成 .pyc
#   PIP_NO_CACHE_DIR=1              不缓存 wheel
#   PIP_DISABLE_PIP_VERSION_CHECK=1 关闭 pip 版本检查
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PIP_NO_CACHE_DIR=1 \
    PIP_DISABLE_PIP_VERSION_CHECK=1

# 安装编译工具链
#   gcc / gcc-c++ / make      编译 C 扩展（mysqlclient、uwsgi 等）
#   openssl-devel             cryptography、_ssl 等
#   bzip2-devel / libffi-devel
#   mariadb-devel             编译 mysqlclient（提供 .pc 文件）
#   pkgconf-pkg-config        提供 pkg-config 命令（mysqlclient 2.2.x 必需）
RUN set -eux; \
    # 替换 dnf 源为阿里云镜像
    sed -e 's|^mirrorlist=|#mirrorlist=|g' \
        -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
        -i.bak /etc/yum.repos.d/*.repo; \
    dnf install -y --setopt=install_weak_deps=False \
        gcc gcc-c++ make \
        openssl-devel bzip2-devel libffi-devel \
        mariadb-devel pkgconf-pkg-config; \
    dnf clean all; rm -rf /var/cache/dnf

# 配置 pip 国内镜像源（阿里云 PyPI）
RUN pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple && \
    pip3 config set install.trusted-host mirrors.aliyun.com

# 只拷 requirements.txt
#   源码变化但依赖未变时，可复用 pip install 层缓存
WORKDIR /opt/apps
COPY ${VAR_PYFILE_PATH}/requirements.txt ./

# 依赖装到 /opt/deps，与基础镜像 Python 目录解耦
#   --prefix=/opt/deps  安装到独立目录，runtime 只 COPY 这个目录的产物
#   uwsgi               生产环境 WSGI 服务器，单独安装
RUN python3 -m pip install --prefix=/opt/deps -r requirements.txt && \
    python3 -m pip install --prefix=/opt/deps uwsgi


# ============================================================
# 阶段二：runtime —— 最终业务镜像
# ============================================================
FROM ${VAR_BASE_IMAGE} AS runtime

# 阶段内重新声明
ARG VAR_PYTHON_PREFIX
ARG VAR_PYTHON_SHORT_VERSION
ARG VAR_PROFILES
ARG VAR_PORT
ARG VAR_PYFILE
ARG VAR_PYFILE_PATH

LABEL MAINTAINER="djangoadmin@126.com"

# 运行期环境变量
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1

# ARG 转 ENV，运行期可读取
#   PORT     供 EXPOSE 与 CMD 使用
#   PYFILE   入口文件名
#   PROFILES 应用读取的 profile
ENV PORT=${VAR_PORT} \
    PYFILE=${VAR_PYFILE} \
    PROFILES=${VAR_PROFILES}

# 把 builder 编译好的 site-packages 和可执行文件拷到基础镜像 Python 对应目录
# 目标路径必须与基础镜像 Python 的实际 site-packages 一致
# 用 COPY --chown 指定属主，避免额外的 chown 层
COPY --chown=esxi:esxi --from=builder \
     /opt/deps/lib/python${VAR_PYTHON_SHORT_VERSION}/site-packages/ \
     ${VAR_PYTHON_PREFIX}/lib/python${VAR_PYTHON_SHORT_VERSION}/site-packages/
COPY --chown=esxi:esxi --from=builder /opt/deps/bin/ ${VAR_PYTHON_PREFIX}/bin/

WORKDIR /opt/apps

# 拷项目源码（放在依赖之后，保护 pip 层缓存）
# 建议配合 .dockerignore 排除 .git、__pycache__、本地虚拟环境等
COPY --chown=esxi:esxi ${VAR_PYFILE_PATH}/ ./

USER esxi
EXPOSE ${PORT}

# 启动命令
#   ${PYFILE} 为入口文件名（不含 .py），如 manage
#   runserver 仅适合开发/调试；生产环境建议改用 uwsgi / gunicorn，例如：
#   CMD ["sh","-c","uwsgi --http 0.0.0.0:${PORT} \
#        --module 你的项目名.wsgi:application \
#        --processes 4 --threads 2"]
CMD ["sh", "-c", "uvicorn src.main:app --host 0.0.0.0 --port ${PORT}"]