diff --git a/.jenkins/.env.yml b/.jenkins/.env.yml new file mode 100644 index 0000000..a17137b --- /dev/null +++ b/.jenkins/.env.yml @@ -0,0 +1,16 @@ +masterProfiles: ['','uat','prod'] +Profiles: ['','dev'] +jobConfigFile: "djangoadminConfig.yml" +npmCompileCMD: | + export PATH=/usr/local/node/bin:$PATH + set -e \ + && yarn config set registry https://registry.npmmirror.com \ + && yarn config get registry \ + && yarn config set strict-ssl false \ + && yarn config set sass_binary_site https://repo.huaweicloud.com/node-sass/node-sass \ + && rm -rf package-lock.json \ + && rm -rf node_modules/.cache 2>/dev/null || true \ + && yarn cache clean --force \ + && yarn global add node-gyp@10.3.1 \ + && yarn install --unsafe-perm --legacy-peer-deps --network-timeout 300000 \ + && yarn run build:${PROFILE} \ No newline at end of file diff --git a/.jenkins/Dockerfile b/.jenkins/Dockerfile new file mode 100644 index 0000000..5b9ff51 --- /dev/null +++ b/.jenkins/Dockerfile @@ -0,0 +1,142 @@ +# ============================================================ +# 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}"] \ No newline at end of file diff --git a/.jenkins/Jenkinsfile b/.jenkins/Jenkinsfile new file mode 100644 index 0000000..8129435 --- /dev/null +++ b/.jenkins/Jenkinsfile @@ -0,0 +1,3 @@ +@Library('share-library@master')_ +orgName = 'djangoadmin' +pipelinePythonService(orgName) \ No newline at end of file diff --git a/.jenkins/Jenkinsfile2 b/.jenkins/Jenkinsfile2 new file mode 100644 index 0000000..2cf3edd --- /dev/null +++ b/.jenkins/Jenkinsfile2 @@ -0,0 +1,3 @@ +@Library('share-library@master')_ +orgName = 'djangoadmin' +pipelineNodeService(orgName) \ No newline at end of file