更新
This commit is contained in:
@@ -1,149 +1,237 @@
|
|||||||
# 使用CentOS 8作为基础镜像
|
# ============================================================================
|
||||||
FROM centos:8
|
# 基础镜像构建文件: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="小蚂蚁云团队" \
|
LABEL maintainer="小蚂蚁云团队" \
|
||||||
version="1.0" \
|
version="2.1" \
|
||||||
description="基于CentOS 8的Python 3.12.8运行环境" \
|
description="基于CentOS 8的Python 3.12.8精简运行环境(含 MySQL/SQLite 运行时库)" \
|
||||||
python.version="3.12.8"
|
python.version="3.12.8"
|
||||||
|
|
||||||
# 设置环境变量
|
# ----------------------------------------------------------------------------
|
||||||
|
# 运行时环境变量
|
||||||
|
# PYTHON_HOME : 与 builder 保持一致,便于 COPY 路径引用
|
||||||
|
# TZ : 时区
|
||||||
|
# LANG : 默认语言环境
|
||||||
|
# PATH : 把 Python 的 bin 目录放到最前,保证 python/pip 生效
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
ENV PYTHON_VERSION=3.12.8 \
|
ENV PYTHON_VERSION=3.12.8 \
|
||||||
PYTHON_HOME=/usr/local/python3.12.8 \
|
PYTHON_HOME=/usr/local/python3.12.8 \
|
||||||
TZ=Asia/Shanghai \
|
TZ=Asia/Shanghai \
|
||||||
LANG=en_US.UTF-8
|
LANG=en_US.UTF-8 \
|
||||||
|
PATH=/usr/local/python3.12.8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
|
||||||
# 设置工作目录
|
# ----------------------------------------------------------------------------
|
||||||
WORKDIR /tmp
|
# 安装运行时所需的系统库(注意:全部是运行时库,不是 -devel 开发包)
|
||||||
|
# openssl-libs : _ssl 模块依赖
|
||||||
# 第一步:修复CentOS 8的软件源并安装编译工具
|
# 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; \
|
RUN set -eux; \
|
||||||
\
|
# ---- 把 CentOS 8 官方源替换为阿里云 rockylinux 镜像 ----
|
||||||
# 由于CentOS 8已停止维护,需要修改软件源
|
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
|
||||||
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && \
|
-e 's|^#baseurl=http://mirror.centos.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
|
||||||
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* && \
|
-i.bak /etc/yum.repos.d/CentOS-*.repo; \
|
||||||
\
|
# ---- 安装运行时依赖 ----
|
||||||
# 更新系统并安装必要的开发工具
|
dnf install -y --setopt=install_weak_deps=False \
|
||||||
dnf update -y && \
|
openssl-libs \
|
||||||
dnf install -y \
|
bzip2-libs \
|
||||||
make \
|
libffi \
|
||||||
gcc \
|
zlib \
|
||||||
gcc-c++ \
|
readline \
|
||||||
kernel-devel \
|
sqlite-libs \
|
||||||
openssl-devel \
|
mariadb-connector-c \
|
||||||
bzip2-devel \
|
|
||||||
libffi-devel \
|
|
||||||
zlib-devel \
|
|
||||||
readline-devel \
|
|
||||||
sqlite-devel \
|
|
||||||
# 系统工具
|
|
||||||
curl \
|
|
||||||
tar \
|
|
||||||
xz \
|
|
||||||
gzip \
|
|
||||||
git \
|
|
||||||
glibc-langpack-en \
|
glibc-langpack-en \
|
||||||
shadow-utils \
|
shadow-utils \
|
||||||
which \
|
tzdata; \
|
||||||
&& \
|
# ---- 清理缓存 ----
|
||||||
|
dnf clean all; rm -rf /var/cache/dnf; \
|
||||||
\
|
\
|
||||||
# 清理缓存以减少镜像大小
|
# ---- 时区配置 ----
|
||||||
dnf clean all && \
|
ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime; \
|
||||||
rm -rf /var/cache/dnf; \
|
echo ${TZ} > /etc/timezone; \
|
||||||
\
|
# ---- 语言环境配置 ----
|
||||||
# 配置时区
|
echo 'LANG="en_US.UTF-8"' > /etc/locale.conf; \
|
||||||
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
|
echo 'LC_ALL="en_US.UTF-8"' >> /etc/locale.conf
|
||||||
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; \
|
RUN set -eux; \
|
||||||
\
|
ln -sf ${PYTHON_HOME}/bin/python3.12 /usr/bin/python3; \
|
||||||
# 检查编译器是否安装成功
|
ln -sf ${PYTHON_HOME}/bin/python3.12 /usr/bin/python; \
|
||||||
echo "=== 检查编译工具 ==="; \
|
ln -sf ${PYTHON_HOME}/bin/pip3 /usr/bin/pip; \
|
||||||
make --version; \
|
echo "${PYTHON_HOME}/lib" > /etc/ld.so.conf.d/python3.conf; \
|
||||||
gcc --version; \
|
ldconfig; \
|
||||||
g++ --version;
|
python3 --version; pip --version
|
||||||
|
|
||||||
# 添加Python安装包(确保Python-3.12.8.tar.xz在构建上下文)
|
# ----------------------------------------------------------------------------
|
||||||
ADD Python-3.12.8.tar.xz /tmp/
|
# 创建非 root 用户 esxi
|
||||||
|
# 1) groupadd -r : 创建系统组
|
||||||
# 第三步:编译和安装Python
|
# 2) useradd -r : 创建系统用户,家目录 /opt/apps
|
||||||
|
# 3) 把工作目录和 Python 目录的属主交给 esxi
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
RUN set -eux; \
|
RUN set -eux; \
|
||||||
\
|
groupadd -r esxi; \
|
||||||
# 进入解压后的Python目录
|
useradd -r -g esxi -d /opt/apps -s /bin/bash esxi; \
|
||||||
cd /tmp/Python-3.12.8 && \
|
mkdir -p /opt/apps; \
|
||||||
\
|
chown -R esxi:esxi /opt/apps ${PYTHON_HOME}
|
||||||
# 配置编译选项
|
|
||||||
./configure \
|
|
||||||
--prefix=${PYTHON_HOME} \
|
|
||||||
--enable-optimizations \
|
|
||||||
--enable-shared \
|
|
||||||
--with-system-ffi \
|
|
||||||
--with-ensurepip=install \
|
|
||||||
&& \
|
|
||||||
\
|
|
||||||
# 编译和安装
|
|
||||||
make -j$(nproc) && \
|
|
||||||
make install && \
|
|
||||||
\
|
|
||||||
# 创建软链接
|
|
||||||
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 && \
|
|
||||||
\
|
|
||||||
# 清理编译文件和源码
|
|
||||||
cd /tmp && \
|
|
||||||
rm -rf /tmp/Python-3.12.8;
|
|
||||||
|
|
||||||
# 设置全局PATH环境变量
|
# ----------------------------------------------------------------------------
|
||||||
ENV PATH=${PYTHON_HOME}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
# 工作目录 & 运行用户
|
||||||
|
# - WORKDIR 在 USER 之前设置,避免权限问题
|
||||||
# 第四步:验证Python安装
|
# - USER esxi 让容器以非 root 身份运行,提升安全性
|
||||||
RUN set -eux; \
|
# ----------------------------------------------------------------------------
|
||||||
\
|
|
||||||
# 检查Python版本
|
|
||||||
echo "=== Python版本 ==="; \
|
|
||||||
python3 --version; \
|
|
||||||
python --version; \
|
|
||||||
\
|
|
||||||
# 检查pip版本
|
|
||||||
echo "=== Pip版本 ==="; \
|
|
||||||
pip --version;
|
|
||||||
|
|
||||||
# 第五步:升级pip和安装常用工具
|
|
||||||
RUN set -eux; \
|
|
||||||
\
|
|
||||||
# 升级pip
|
|
||||||
pip install --upgrade pip setuptools wheel && \
|
|
||||||
\
|
|
||||||
# 安装常用Python工具
|
|
||||||
pip install virtualenv;
|
|
||||||
|
|
||||||
# 设置工作目录(Python项目目录)
|
|
||||||
WORKDIR /opt/apps
|
WORKDIR /opt/apps
|
||||||
|
USER esxi
|
||||||
|
|
||||||
# 创建非root用户用于运行Python应用
|
# ----------------------------------------------------------------------------
|
||||||
RUN set -eux; \
|
# 健康检查:每 30s 检查一次 python3 是否可用
|
||||||
\
|
# ----------------------------------------------------------------------------
|
||||||
# 创建用户和组
|
|
||||||
groupadd -r esxi && \
|
|
||||||
useradd -r -g esxi -d /opt/apps -s /bin/bash esxi && \
|
|
||||||
\
|
|
||||||
# 设置目录权限
|
|
||||||
chown -R esxi:esxi /opt/apps && \
|
|
||||||
chown -R esxi:esxi ${PYTHON_HOME};
|
|
||||||
|
|
||||||
# 设置健康检查
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
CMD python3 --version > /dev/null 2>&1 || exit 1
|
CMD python3 --version > /dev/null 2>&1 || exit 1
|
||||||
|
|
||||||
# 设置默认启动命令
|
# ----------------------------------------------------------------------------
|
||||||
|
# 默认启动命令(可被子镜像或 docker run 覆盖)
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
CMD ["python3", "--version"]
|
CMD ["python3", "--version"]
|
||||||
Reference in New Issue
Block a user