Files
jenkins-docker-images/dockerfiles/python/3.12.8-centos8-dos/Dockerfile
T
2026-09-11 22:48:17 +08:00

237 lines
11 KiB
Docker
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================================================
# 基础镜像构建文件:CentOS 8 + Python 3.12.8(多阶段、精简版)
# 作者:小蚂蚁云团队
# 说明:
# 采用「builder + runtime」两阶段构建:
# - builder 阶段:安装编译工具链(含 make/cmake/mariadb-devel/sqlite-devel),
# 编译 Python,并裁剪安装目录
# - runtime 阶段:只拷贝编译好的 Python + 运行时库,不携带任何编译工具
# 最终镜像体积约为单阶段版本的 1/3。
#
# 注:CentOS 8 已于 2021-12-31 EOL,官方源已下线。
# 本脚本把 dnf 源切换到阿里云 rockylinux 镜像(与 CentOS 8 二进制兼容),
# 保证 dnf install 仍然可用。
# ============================================================================
# ============================================================================
# 阶段一:builder —— 只负责编译 Python,产物最终会被丢弃
# ============================================================================
FROM centos:8 AS builder
# ----------------------------------------------------------------------------
# 环境变量
# PYTHON_VERSION : Python 版本号,便于统一引用
# PYTHON_HOME : Python 安装前缀目录(--prefix 使用)
# LANG : 编译期语言环境,避免 make/configure 中文乱码
# ----------------------------------------------------------------------------
ENV PYTHON_VERSION=3.12.8 \
PYTHON_HOME=/usr/local/python3.12.8 \
LANG=en_US.UTF-8
# ----------------------------------------------------------------------------
# 安装编译 Python 所需的工具链与依赖库
# 关键点:
# 1) CentOS 8 官方源已 EOL,切换到阿里云 rockylinux 镜像(二进制兼容)
# 2) --setopt=install_weak_deps=False 不安装弱依赖,减少包数量
# 3) 编译完成后立即 dnf clean all,清除缓存
# 4) 加入 make / cmake / mariadb-devel / sqlite-devel:
# - make : Python 自身编译必需
# - cmake : 第三方 C 扩展(如部分数据库/科学计算库)构建用
# - mariadb-devel : 提供 mysql.h / mysql_config,编译 MySQL C 扩展用
# (CentOS 8 里 mysql-devel 已被 mariadb-devel 取代)
# - sqlite-devel : Python _sqlite3 模块编译必需
# 5) 不装 kernel-devel(除非要编译内核模块)
# ----------------------------------------------------------------------------
RUN set -eux; \
# ---- 把 CentOS 8 官方源替换为阿里云 rockylinux 镜像 ----
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://mirror.centos.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
-i.bak /etc/yum.repos.d/CentOS-*.repo; \
# ---- 安装编译依赖 ----
dnf install -y --setopt=install_weak_deps=False \
make cmake gcc gcc-c++ \
openssl-devel bzip2-devel libffi-devel \
zlib-devel readline-devel sqlite-devel \
mariadb-devel \
xz tar findutils; \
# ---- 清理 dnf 缓存 ----
dnf clean all; rm -rf /var/cache/dnf
# ----------------------------------------------------------------------------
# 把 Python 源码包 ADD 进来
# - ADD 会自动解压 .tar.xz
# - 该 tar.xz 只存在于 builder 阶段,最终镜像不会包含它
# - 前提:构建上下文里需要有 Python-3.12.8.tar.xz
# ----------------------------------------------------------------------------
ADD Python-3.12.8.tar.xz /tmp/
# ----------------------------------------------------------------------------
# 编译并安装 Python
# 关键点:
# 1) 去掉 --enable-optimizations(PGO 训练会导致编译时间从几分钟涨到 20~40 分钟)
# 2) --enable-shared 生成 libpython3.12.so,方便其他程序链接
# 3) --with-system-ffi 使用系统 libffi,避免自编译
# 4) --with-ensurepip=install 安装 pip
# 5) 安装完成后对 Python 目录做「瘦身」:
# - 删除 test/idlelib/tkinter/turtledemo/lib2to3 等运行时用不到的模块
# - 保留 ensurepip 与 site-packages,否则 pip 会被一并删除
# - 删除静态库 .a、libtool 文件 .la、__pycache__、.pyc
# - 对 .so 执行 strip,去掉调试符号
# 6) 最后删除源码目录,避免残留在 builder 层
# ----------------------------------------------------------------------------
RUN set -eux; \
cd /tmp/Python-3.12.8; \
./configure \
--prefix=${PYTHON_HOME} \
--enable-shared \
--with-system-ffi \
--with-ensurepip=install; \
make -j"$(nproc)"; \
make install; \
\
# ---- 裁剪 Python 安装目录,去掉运行时不需要的内容 ----
# 注意:不要删 ensurepip,也不要删 site-packages/*
cd ${PYTHON_HOME}; \
rm -rf lib/python3.12/test \
lib/python3.12/idlelib \
lib/python3.12/tkinter \
lib/python3.12/turtledemo \
lib/python3.12/lib2to3 \
lib/python3.12/config-3.12-*; \
# ---- 删除 Python 缓存文件 ----
find ${PYTHON_HOME} -name '__pycache__' -type d -exec rm -rf {} + 2>/dev/null || true; \
find ${PYTHON_HOME} -name '*.pyc' -delete; \
# ---- 删除静态库和 libtool 文件 ----
find ${PYTHON_HOME} -name '*.a' -delete; \
find ${PYTHON_HOME} -name '*.la' -delete; \
# ---- 剥离 .so 动态库的调试符号 ----
find ${PYTHON_HOME}/bin ${PYTHON_HOME}/lib -type f -name '*.so*' \
-exec strip --strip-unneeded {} + 2>/dev/null || true; \
\
# ---- 清理源码目录 ----
cd /tmp; rm -rf /tmp/Python-3.12.8
# ============================================================================
# 阶段二:runtime —— 最终镜像
# 只包含:运行时依赖库 + 从 builder 拷贝过来的 Python
# ============================================================================
FROM centos:8 AS runtime
# ----------------------------------------------------------------------------
# 镜像元数据(LABEL 不影响镜像体积)
# ----------------------------------------------------------------------------
LABEL maintainer="小蚂蚁云团队" \
version="2.1" \
description="基于CentOS 8的Python 3.12.8精简运行环境(含 MySQL/SQLite 运行时库)" \
python.version="3.12.8"
# ----------------------------------------------------------------------------
# 运行时环境变量
# PYTHON_HOME : 与 builder 保持一致,便于 COPY 路径引用
# TZ : 时区
# LANG : 默认语言环境
# PATH : 把 Python 的 bin 目录放到最前,保证 python/pip 生效
# ----------------------------------------------------------------------------
ENV PYTHON_VERSION=3.12.8 \
PYTHON_HOME=/usr/local/python3.12.8 \
TZ=Asia/Shanghai \
LANG=en_US.UTF-8 \
PATH=/usr/local/python3.12.8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# ----------------------------------------------------------------------------
# 安装运行时所需的系统库(注意:全部是运行时库,不是 -devel 开发包)
# openssl-libs : _ssl 模块依赖
# bzip2-libs : _bz2 模块依赖
# libffi : _ctypes 模块依赖
# zlib : zlib 模块依赖
# readline : 交互式命令行
# sqlite-libs : _sqlite3 模块依赖(对应 builder 的 sqlite-devel)
# mariadb-connector-c : MySQL/MariaDB 客户端运行库
# (对应 builder 的 mariadb-devel,
# 编译出的 mysqlclient 等 C 扩展运行需要)
# glibc-langpack-en : en_US.UTF-8 locale
# shadow-utils : useradd/groupadd 等
# tzdata : 时区数据
# 同时完成:时区、locale 配置
# ----------------------------------------------------------------------------
RUN set -eux; \
# ---- 把 CentOS 8 官方源替换为阿里云 rockylinux 镜像 ----
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://mirror.centos.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
-i.bak /etc/yum.repos.d/CentOS-*.repo; \
# ---- 安装运行时依赖 ----
dnf install -y --setopt=install_weak_deps=False \
openssl-libs \
bzip2-libs \
libffi \
zlib \
readline \
sqlite-libs \
mariadb-connector-c \
glibc-langpack-en \
shadow-utils \
tzdata; \
# ---- 清理缓存 ----
dnf clean all; rm -rf /var/cache/dnf; \
\
# ---- 时区配置 ----
ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime; \
echo ${TZ} > /etc/timezone; \
# ---- 语言环境配置 ----
echo 'LANG="en_US.UTF-8"' > /etc/locale.conf; \
echo 'LC_ALL="en_US.UTF-8"' >> /etc/locale.conf
# ----------------------------------------------------------------------------
# 从 builder 阶段拷贝编译好的 Python
# - 只拷贝 ${PYTHON_HOME},编译工具链完全不进入最终镜像
# - 路径保持一致,避免 PATH 失效
# ----------------------------------------------------------------------------
COPY --from=builder ${PYTHON_HOME} ${PYTHON_HOME}
# ----------------------------------------------------------------------------
# 建立 python/pip 软链,并注册动态链接库
# 1) /usr/bin/python3、python、pip 指向 Python 安装目录
# 2) 把 ${PYTHON_HOME}/lib 写入 ld.so.conf.d 并执行 ldconfig
# 否则运行 python 时会报 "libpython3.12.so not found"
# 3) 最后验证 python3 / pip 是否可用
# ----------------------------------------------------------------------------
RUN set -eux; \
ln -sf ${PYTHON_HOME}/bin/python3.12 /usr/bin/python3; \
ln -sf ${PYTHON_HOME}/bin/python3.12 /usr/bin/python; \
ln -sf ${PYTHON_HOME}/bin/pip3 /usr/bin/pip; \
echo "${PYTHON_HOME}/lib" > /etc/ld.so.conf.d/python3.conf; \
ldconfig; \
python3 --version; pip --version
# ----------------------------------------------------------------------------
# 创建非 root 用户 esxi
# 1) groupadd -r : 创建系统组
# 2) useradd -r : 创建系统用户,家目录 /opt/apps
# 3) 把工作目录和 Python 目录的属主交给 esxi
# ----------------------------------------------------------------------------
RUN set -eux; \
groupadd -r esxi; \
useradd -r -g esxi -d /opt/apps -s /bin/bash esxi; \
mkdir -p /opt/apps; \
chown -R esxi:esxi /opt/apps ${PYTHON_HOME}
# ----------------------------------------------------------------------------
# 工作目录 & 运行用户
# - WORKDIR 在 USER 之前设置,避免权限问题
# - USER esxi 让容器以非 root 身份运行,提升安全性
# ----------------------------------------------------------------------------
WORKDIR /opt/apps
USER esxi
# ----------------------------------------------------------------------------
# 健康检查:每 30s 检查一次 python3 是否可用
# ----------------------------------------------------------------------------
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD python3 --version > /dev/null 2>&1 || exit 1
# ----------------------------------------------------------------------------
# 默认启动命令(可被子镜像或 docker run 覆盖)
# ----------------------------------------------------------------------------
CMD ["python3", "--version"]