From e390fabc249c10435f349e2b1ae3a81af003b5ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=9A=82=E8=9A=81=E4=BA=91?= Date: Sat, 12 Sep 2026 02:14:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jenkins/Dockerfile | 228 +++++++++++++++++-------------------------- .jenkins/Dockerfile2 | 200 +++++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+), 137 deletions(-) create mode 100644 .jenkins/Dockerfile2 diff --git a/.jenkins/Dockerfile b/.jenkins/Dockerfile index 680f8f5..b18b41c 100644 --- a/.jenkins/Dockerfile +++ b/.jenkins/Dockerfile @@ -1,200 +1,154 @@ # ============================================================ -# Dockerfile:多阶段构建 Python 应用镜像 +# Dockerfile:单阶段构建 Python 应用镜像(RockyLinux 8 + Python 3.12.8) # -# 构建思路: -# - builder 阶段:安装编译工具链,编译并安装 Python 依赖 -# - runtime 阶段:只保留运行期必需内容,丢弃编译器 +# 设计思路: +# - 单阶段构建,所有依赖一次装齐,避免多阶段"包找不到/库缺失"问题 +# - 编译工具链和运行库都保留在最终镜像里,换取构建稳定性和排错简单 +# - 通过 --build-arg 动态注入变量,便于 CI 复用同一份 Dockerfile # -# 通过 --build-arg 动态注入以下变量,便于在 CI 中复用同一份 Dockerfile: -# VAR_BASE_IMAGE 基础镜像(如 python:3.12-slim、自定义的带 esxi 用户的镜像) -# VAR_PYTHON_PREFIX Python 安装前缀(依赖安装位置) -# VAR_PYFILE_PATH 项目源码目录(相对构建上下文) -# VAR_PROFILES 应用 profile(dev / prod ...) +# 构建参数说明: +# VAR_BASE_IMAGE 基础镜像(RockyLinux 8 + Python 3.12.8 + esxi 用户) +# VAR_PROFILES 应用 profile(dev / prod) # VAR_PORT 应用监听端口 -# VAR_PYFILE 启动入口文件名(不含 .py) +# VAR_PYFILE 启动入口文件名(不含 .py),如 manage +# VAR_PYFILE_PATH 项目源码目录(相对构建上下文) # ============================================================ # ------------------------------------------------------------ # 声明构建参数 -# 基础镜像用 ARG 而不是直接 FROM,方便 CI 动态切换 -# Python 前缀单独抽出,避免在 COPY / pip --prefix 里重复硬编码 # ------------------------------------------------------------ ARG VAR_BASE_IMAGE -ARG VAR_PYTHON_PREFIX=/usr/local/python3.12.8 - -# ============================================================ -# 阶段一:builder —— 编译并安装 Python 依赖 -# ============================================================ -FROM ${VAR_BASE_IMAGE} AS builder - -# 基础镜像末尾可能设置了非 root 用户(如 esxi), -# 这里切回 root,否则 yum install 会因权限不足失败 -USER root - -# 镜像作者信息(仅元数据) -LABEL MAINTAINER="djangoadmin@126.com" # ------------------------------------------------------------ -# 编译阶段环境变量 -# PYTHONUNBUFFERED=1 Python 输出不缓冲,日志实时可见 -# PYTHONDONTWRITEBYTECODE=1 不生成 .pyc,避免污染构建产物 -# PIP_NO_CACHE_DIR=1 pip 不缓存 wheel,减小体积 -# PIP_DISABLE_PIP_VERSION_CHECK=1 关闭 pip 版本检查,加快安装 +# 基础镜像 # ------------------------------------------------------------ -ENV PYTHONUNBUFFERED=1 \ - PYTHONDONTWRITEBYTECODE=1 \ - PIP_NO_CACHE_DIR=1 \ - PIP_DISABLE_PIP_VERSION_CHECK=1 - -# ------------------------------------------------------------ -# 安装编译工具链与开发头文件 -# yum-utils / net-tools 基础系统工具 -# gcc / gcc-c++ C/C++ 编译器(编译 C 扩展必需) -# make / cmake 构建工具 -# openssl-devel 编译 _ssl / cryptography -# bzip2-devel 编译 _bz2 -# libffi-devel 编译 _ctypes -# mysql-devel 编译 mysqlclient 等 MySQL 驱动 -# 末尾清理 yum 缓存,避免缓存进入镜像层 -# ------------------------------------------------------------ -RUN yum install -y yum-utils net-tools && \ - yum install -y gcc gcc-c++ make cmake \ - openssl-devel bzip2-devel libffi-devel \ - mariadb-devel pkgconf-pkg-config && \ - yum clean all && rm -rf /var/cache/yum - -#RUN --mount=type=cache,target=/var/cache/dnf,sharing=locked,id=dnf-cache \ -# dnf install -y yum-utils net-tools && \ -# dnf install -y gcc gcc-c++ make cmake \ -# openssl-devel bzip2-devel libffi-devel \ -# mariadb-devel pkgconf-pkg-config - -# ------------------------------------------------------------ -# 配置 pip 国内镜像并升级 pip / setuptools / wheel -# 老版本的 pip 解析依赖容易出错,先升级到最新 -# ------------------------------------------------------------ -RUN pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple && \ - pip3 config set install.trusted-host mirrors.aliyun.com && \ - python3 -m pip install --upgrade pip setuptools wheel - -# ------------------------------------------------------------ -# 拷贝依赖清单 -# 只拷贝 requirements.txt 而不是整个项目, -# 这样源码变化但 requirements 未变时可以复用 pip install 层缓存 -# ------------------------------------------------------------ -ARG VAR_PYFILE_PATH -WORKDIR /opt/apps -COPY ${VAR_PYFILE_PATH}/requirements.txt ./ - -# ------------------------------------------------------------ -# 将依赖安装到 Python 的 prefix 下 -# --prefix=${VAR_PYTHON_PREFIX} 与 runtime 阶段的拷贝路径保持一致 -# python3 -m pip 确保使用同一个解释器 -# uwsgi 生产环境 WSGI 服务器,单独安装 -# 注意:末尾不要多写反斜杠,否则会把下一行注释拼进来导致语法错误 -# ------------------------------------------------------------ -RUN python3 -m pip install --prefix=${VAR_PYTHON_PREFIX} -r requirements.txt && \ - python3 -m pip install --prefix=${VAR_PYTHON_PREFIX} uwsgi - -# ============================================================ -# 阶段二:runtime —— 只保留运行时内容 -# ============================================================ -FROM ${VAR_BASE_IMAGE} AS runtime - -# 切回 root 以便 yum install / chown -USER root +FROM ${VAR_BASE_IMAGE} # 镜像作者信息 -LABEL MAINTAINER="djangoadmin@126.com" +LABEL MAINTAINER="djangoadmin@163.com" # ------------------------------------------------------------ -# 运行期环境变量 -# PYTHONUNBUFFERED=1 日志实时输出,便于 docker logs 观察 -# PYTHONDONTWRITEBYTECODE=1 不写 .pyc,避免容器内产生垃圾文件 +# 切回 root +# 基础镜像末尾通常设置了非 root 用户(如 esxi), +# 不切回 root,后面的 dnf install / mkdir / chown 都会因权限不足失败 +# ------------------------------------------------------------ +USER root + +# ------------------------------------------------------------ +# Python 运行期环境变量 +# PYTHONUNBUFFERED=1 Python 输出不缓冲,日志实时可见 +# PYTHONDONTWRITEBYTECODE=1 不生成 .pyc,避免容器内产生垃圾文件 # ------------------------------------------------------------ ENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 # ------------------------------------------------------------ -# 运行期构建参数 -# VAR_PYTHON_PREFIX Python 前缀(必须与 builder 保持一致) -# VAR_PROFILES 配置 profile(dev / prod) -# VAR_PORT 应用监听端口 -# VAR_PYFILE 启动入口文件名(不含 .py) -# VAR_PYFILE_PATH 项目源码目录 +# 声明运行期构建参数 # ------------------------------------------------------------ -ARG VAR_PYTHON_PREFIX=/usr/local/python3.12.8 ARG VAR_PROFILES ARG VAR_PORT ARG VAR_PYFILE ARG VAR_PYFILE_PATH # ------------------------------------------------------------ -# 将 ARG 转成 ENV,运行期可通过环境变量读取 -# PORT 供 EXPOSE 与 CMD 使用 -# PYFILE 入口文件名 -# PROFILES 应用读取的 profile +# 将 ARG 转为 ENV,运行期可通过环境变量读取 # ------------------------------------------------------------ ENV PORT=${VAR_PORT} \ PYFILE=${VAR_PYFILE} \ PROFILES=${VAR_PROFILES} # ------------------------------------------------------------ -# 安装运行期依赖 -# 只装运行库,不装 -devel 头文件,可显著减小镜像体积: -# net-tools netstat 等网络排查工具(如不需要可去掉) -# openssl-libs SSL 运行库(替代 openssl-devel) -# bzip2-libs bz2 运行库(替代 bzip2-devel) -# libffi ctypes 运行库(替代 libffi-devel) -# mysql-libs MySQL 客户端运行库(替代 mysql-devel) -# 注意:若应用运行期确实需要头文件(如运行期编译),再改回 -devel +# 安装系统依赖(dnf 源换成国内镜像) +# +# RockyLinux 8 官方源可用,但换阿里云镜像更快: +# baseurl=https://mirrors.aliyun.com/rockylinux +# +# 编译期工具: +# gcc / gcc-c++ C/C++ 编译器 +# make / cmake 构建工具 +# openssl-devel 编译 _ssl / cryptography +# bzip2-devel 编译 _bz2 +# libffi-devel 编译 _ctypes +# mariadb-devel 编译 mysqlclient(提供 .pc 文件) +# pkgconf-pkg-config 提供 pkg-config 命令(mysqlclient 2.2.x 必需) +# +# 运行期库: +# net-tools netstat 等网络排查工具 +# openssl-libs SSL 运行库 +# bzip2-libs bz2 运行库 +# libffi ctypes 运行库 +# mariadb-connector-c MySQL/MariaDB 客户端运行库 +# +# 注意: +# 1) RockyLinux 8 里 MySQL 实际由 MariaDB 提供, +# 运行库包名为 mariadb-connector-c(不是 mysql-libs) +# 2) mariadb-devel 和 mysql-devel 不要同时安装,会冲突 +# 3) 末尾清理 dnf 缓存,避免缓存进入镜像层 # ------------------------------------------------------------ -RUN yum install -y net-tools openssl-libs bzip2-libs libffi mysql-libs && \ - yum clean all && rm -rf /var/cache/yum +RUN set -eux; \ + # ---- 把 RockyLinux 8 官方源替换为阿里云镜像 ---- + 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 \ + yum-utils net-tools \ + gcc gcc-c++ make cmake \ + openssl-devel bzip2-devel libffi-devel \ + mariadb-devel pkgconf-pkg-config \ + openssl-libs bzip2-libs libffi mariadb-connector-c; \ + # ---- 清理 dnf 缓存,减小镜像体积 ---- + dnf clean all; rm -rf /var/cache/dnf # ------------------------------------------------------------ -# 从 builder 拷贝已编译安装好的 Python 及依赖 -# 源与目标都使用 ${VAR_PYTHON_PREFIX},保证 runtime 的 Python -# 能在自己的 site-packages 里找到 Django 等包 +# 配置 pip 国内镜像源(阿里云 PyPI) # ------------------------------------------------------------ -COPY --from=builder ${VAR_PYTHON_PREFIX} ${VAR_PYTHON_PREFIX} +RUN pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple && \ + pip3 config set install.trusted-host mirrors.aliyun.com # ------------------------------------------------------------ -# 工作区 +# 升级 pip / setuptools / wheel +# --no-cache-dir 避免 pip 缓存进入镜像层 # ------------------------------------------------------------ +RUN python3 -m pip install --upgrade --no-cache-dir pip setuptools wheel + +# ------------------------------------------------------------ +# 创建工作区 +# ------------------------------------------------------------ +RUN mkdir -p /opt/apps WORKDIR /opt/apps # ------------------------------------------------------------ # 拷贝项目源码 -# 建议配合 .dockerignore 排除 .git、__pycache__、本地虚拟环境等 # ------------------------------------------------------------ COPY ${VAR_PYFILE_PATH}/ ./ # ------------------------------------------------------------ -# 一次性修正属主: -# /opt/apps 保证 esxi 可读写源码 -# ${VAR_PYTHON_PREFIX} 保证 esxi 可访问 Python 及其 site-packages -# 合并成一条 RUN,减少镜像层 +# 安装 Python 依赖 +# -r requirements.txt 项目依赖 +# uwsgi 生产环境 WSGI 服务器 # ------------------------------------------------------------ -RUN chown -R esxi:esxi /opt/apps ${VAR_PYTHON_PREFIX} +RUN python3 -m pip install --no-cache-dir -r requirements.txt && \ + python3 -m pip install --no-cache-dir uwsgi # ------------------------------------------------------------ -# 切回非 root 用户运行应用(安全加固) +# 修正属主 +# ------------------------------------------------------------ +RUN chown -R esxi:esxi /opt/apps + +# ------------------------------------------------------------ +# 切回非 root 用户运行应用 # ------------------------------------------------------------ USER esxi # ------------------------------------------------------------ -# 声明暴露端口(实际映射由 docker run -p 决定) +# 声明暴露端口 # ------------------------------------------------------------ EXPOSE ${PORT} # ------------------------------------------------------------ # 启动命令 -# 使用 sh -c 以便解析 ${PYFILE}、${PORT} 环境变量 -# 注意:runserver 仅适合开发/调试; -# 生产环境建议改为 uwsgi / gunicorn,例如: -# CMD ["sh","-c","uwsgi --http 0.0.0.0:${PORT} \ -# --module ${PYFILE}.wsgi:application \ -# --processes 4 --threads 2"] +# ${PYFILE} 为入口文件名(不含 .py),如 manage +# 生产环境建议改用 uwsgi # ------------------------------------------------------------ -CMD ["sh", "-c", "python3 manage.py runserver 0.0.0.0:${PORT} --noreload"] \ No newline at end of file +CMD ["sh", "-c", "python3 ${PYFILE}.py runserver 0.0.0.0:${PORT} --noreload"] \ No newline at end of file diff --git a/.jenkins/Dockerfile2 b/.jenkins/Dockerfile2 new file mode 100644 index 0000000..680f8f5 --- /dev/null +++ b/.jenkins/Dockerfile2 @@ -0,0 +1,200 @@ +# ============================================================ +# Dockerfile:多阶段构建 Python 应用镜像 +# +# 构建思路: +# - builder 阶段:安装编译工具链,编译并安装 Python 依赖 +# - runtime 阶段:只保留运行期必需内容,丢弃编译器 +# +# 通过 --build-arg 动态注入以下变量,便于在 CI 中复用同一份 Dockerfile: +# VAR_BASE_IMAGE 基础镜像(如 python:3.12-slim、自定义的带 esxi 用户的镜像) +# VAR_PYTHON_PREFIX Python 安装前缀(依赖安装位置) +# VAR_PYFILE_PATH 项目源码目录(相对构建上下文) +# VAR_PROFILES 应用 profile(dev / prod ...) +# VAR_PORT 应用监听端口 +# VAR_PYFILE 启动入口文件名(不含 .py) +# ============================================================ + +# ------------------------------------------------------------ +# 声明构建参数 +# 基础镜像用 ARG 而不是直接 FROM,方便 CI 动态切换 +# Python 前缀单独抽出,避免在 COPY / pip --prefix 里重复硬编码 +# ------------------------------------------------------------ +ARG VAR_BASE_IMAGE +ARG VAR_PYTHON_PREFIX=/usr/local/python3.12.8 + +# ============================================================ +# 阶段一:builder —— 编译并安装 Python 依赖 +# ============================================================ +FROM ${VAR_BASE_IMAGE} AS builder + +# 基础镜像末尾可能设置了非 root 用户(如 esxi), +# 这里切回 root,否则 yum install 会因权限不足失败 +USER root + +# 镜像作者信息(仅元数据) +LABEL MAINTAINER="djangoadmin@126.com" + +# ------------------------------------------------------------ +# 编译阶段环境变量 +# PYTHONUNBUFFERED=1 Python 输出不缓冲,日志实时可见 +# PYTHONDONTWRITEBYTECODE=1 不生成 .pyc,避免污染构建产物 +# PIP_NO_CACHE_DIR=1 pip 不缓存 wheel,减小体积 +# PIP_DISABLE_PIP_VERSION_CHECK=1 关闭 pip 版本检查,加快安装 +# ------------------------------------------------------------ +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PIP_NO_CACHE_DIR=1 \ + PIP_DISABLE_PIP_VERSION_CHECK=1 + +# ------------------------------------------------------------ +# 安装编译工具链与开发头文件 +# yum-utils / net-tools 基础系统工具 +# gcc / gcc-c++ C/C++ 编译器(编译 C 扩展必需) +# make / cmake 构建工具 +# openssl-devel 编译 _ssl / cryptography +# bzip2-devel 编译 _bz2 +# libffi-devel 编译 _ctypes +# mysql-devel 编译 mysqlclient 等 MySQL 驱动 +# 末尾清理 yum 缓存,避免缓存进入镜像层 +# ------------------------------------------------------------ +RUN yum install -y yum-utils net-tools && \ + yum install -y gcc gcc-c++ make cmake \ + openssl-devel bzip2-devel libffi-devel \ + mariadb-devel pkgconf-pkg-config && \ + yum clean all && rm -rf /var/cache/yum + +#RUN --mount=type=cache,target=/var/cache/dnf,sharing=locked,id=dnf-cache \ +# dnf install -y yum-utils net-tools && \ +# dnf install -y gcc gcc-c++ make cmake \ +# openssl-devel bzip2-devel libffi-devel \ +# mariadb-devel pkgconf-pkg-config + +# ------------------------------------------------------------ +# 配置 pip 国内镜像并升级 pip / setuptools / wheel +# 老版本的 pip 解析依赖容易出错,先升级到最新 +# ------------------------------------------------------------ +RUN pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple && \ + pip3 config set install.trusted-host mirrors.aliyun.com && \ + python3 -m pip install --upgrade pip setuptools wheel + +# ------------------------------------------------------------ +# 拷贝依赖清单 +# 只拷贝 requirements.txt 而不是整个项目, +# 这样源码变化但 requirements 未变时可以复用 pip install 层缓存 +# ------------------------------------------------------------ +ARG VAR_PYFILE_PATH +WORKDIR /opt/apps +COPY ${VAR_PYFILE_PATH}/requirements.txt ./ + +# ------------------------------------------------------------ +# 将依赖安装到 Python 的 prefix 下 +# --prefix=${VAR_PYTHON_PREFIX} 与 runtime 阶段的拷贝路径保持一致 +# python3 -m pip 确保使用同一个解释器 +# uwsgi 生产环境 WSGI 服务器,单独安装 +# 注意:末尾不要多写反斜杠,否则会把下一行注释拼进来导致语法错误 +# ------------------------------------------------------------ +RUN python3 -m pip install --prefix=${VAR_PYTHON_PREFIX} -r requirements.txt && \ + python3 -m pip install --prefix=${VAR_PYTHON_PREFIX} uwsgi + +# ============================================================ +# 阶段二:runtime —— 只保留运行时内容 +# ============================================================ +FROM ${VAR_BASE_IMAGE} AS runtime + +# 切回 root 以便 yum install / chown +USER root + +# 镜像作者信息 +LABEL MAINTAINER="djangoadmin@126.com" + +# ------------------------------------------------------------ +# 运行期环境变量 +# PYTHONUNBUFFERED=1 日志实时输出,便于 docker logs 观察 +# PYTHONDONTWRITEBYTECODE=1 不写 .pyc,避免容器内产生垃圾文件 +# ------------------------------------------------------------ +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 + +# ------------------------------------------------------------ +# 运行期构建参数 +# VAR_PYTHON_PREFIX Python 前缀(必须与 builder 保持一致) +# VAR_PROFILES 配置 profile(dev / prod) +# VAR_PORT 应用监听端口 +# VAR_PYFILE 启动入口文件名(不含 .py) +# VAR_PYFILE_PATH 项目源码目录 +# ------------------------------------------------------------ +ARG VAR_PYTHON_PREFIX=/usr/local/python3.12.8 +ARG VAR_PROFILES +ARG VAR_PORT +ARG VAR_PYFILE +ARG VAR_PYFILE_PATH + +# ------------------------------------------------------------ +# 将 ARG 转成 ENV,运行期可通过环境变量读取 +# PORT 供 EXPOSE 与 CMD 使用 +# PYFILE 入口文件名 +# PROFILES 应用读取的 profile +# ------------------------------------------------------------ +ENV PORT=${VAR_PORT} \ + PYFILE=${VAR_PYFILE} \ + PROFILES=${VAR_PROFILES} + +# ------------------------------------------------------------ +# 安装运行期依赖 +# 只装运行库,不装 -devel 头文件,可显著减小镜像体积: +# net-tools netstat 等网络排查工具(如不需要可去掉) +# openssl-libs SSL 运行库(替代 openssl-devel) +# bzip2-libs bz2 运行库(替代 bzip2-devel) +# libffi ctypes 运行库(替代 libffi-devel) +# mysql-libs MySQL 客户端运行库(替代 mysql-devel) +# 注意:若应用运行期确实需要头文件(如运行期编译),再改回 -devel +# ------------------------------------------------------------ +RUN yum install -y net-tools openssl-libs bzip2-libs libffi mysql-libs && \ + yum clean all && rm -rf /var/cache/yum + +# ------------------------------------------------------------ +# 从 builder 拷贝已编译安装好的 Python 及依赖 +# 源与目标都使用 ${VAR_PYTHON_PREFIX},保证 runtime 的 Python +# 能在自己的 site-packages 里找到 Django 等包 +# ------------------------------------------------------------ +COPY --from=builder ${VAR_PYTHON_PREFIX} ${VAR_PYTHON_PREFIX} + +# ------------------------------------------------------------ +# 工作区 +# ------------------------------------------------------------ +WORKDIR /opt/apps + +# ------------------------------------------------------------ +# 拷贝项目源码 +# 建议配合 .dockerignore 排除 .git、__pycache__、本地虚拟环境等 +# ------------------------------------------------------------ +COPY ${VAR_PYFILE_PATH}/ ./ + +# ------------------------------------------------------------ +# 一次性修正属主: +# /opt/apps 保证 esxi 可读写源码 +# ${VAR_PYTHON_PREFIX} 保证 esxi 可访问 Python 及其 site-packages +# 合并成一条 RUN,减少镜像层 +# ------------------------------------------------------------ +RUN chown -R esxi:esxi /opt/apps ${VAR_PYTHON_PREFIX} + +# ------------------------------------------------------------ +# 切回非 root 用户运行应用(安全加固) +# ------------------------------------------------------------ +USER esxi + +# ------------------------------------------------------------ +# 声明暴露端口(实际映射由 docker run -p 决定) +# ------------------------------------------------------------ +EXPOSE ${PORT} + +# ------------------------------------------------------------ +# 启动命令 +# 使用 sh -c 以便解析 ${PYFILE}、${PORT} 环境变量 +# 注意:runserver 仅适合开发/调试; +# 生产环境建议改为 uwsgi / gunicorn,例如: +# CMD ["sh","-c","uwsgi --http 0.0.0.0:${PORT} \ +# --module ${PYFILE}.wsgi:application \ +# --processes 4 --threads 2"] +# ------------------------------------------------------------ +CMD ["sh", "-c", "python3 manage.py runserver 0.0.0.0:${PORT} --noreload"] \ No newline at end of file