Dockerfile
# 基于 Python 官方轻量镜像
FROM docker.io/python:3.11-slim
# 设置工作目录
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential python3-dev gcc g++ make git \
&& rm -rf /var/lib/apt/lists/*
# 安装 Python 依赖
RUN pip install --no-cache-dir cython setuptools aiohttp
# 默认执行命令:构建 .so
CMD ["python", "setup.py", "build_ext", "--inplace"]
docker-compose.yaml
version: "3.9"
services:
cython-builder:
build:
context: .
dockerfile: Dockerfile
platforms:
- linux/amd64
- linux/arm64
image: cython-build
container_name: cython-build
tty: true
stdin_open: true
volumes:
- .:/app
command: >
bash -c "python setup.py &&
chown -R $(id -u):$(id -g) /app"
setup.py文件
import os
from distutils.core import setup
from Cython.Build import cythonize
def get_all_py_files(dir_root):
"""获取所有的py文件,要编译成so的文件
:params dir_root: 项目根目录地址
"""
res_py_file_list = []
for root, dirs, files in os.walk(dir_root):
# 跳过 .venv 目录
if '.venv' in dirs:
dirs.remove('.venv')
for file in files:
if os.path.splitext(file)[1] != '.py':
continue
if 'to_so.py' in file:
continue
if 'main.py' in file:
continue
_path = os.path.join(root, file) # 使用 os.path.join 生成路径
res_py_file_list.append(_path)
return res_py_file_list
def clean_c_file(dir_root):
for root, dirs, files in os.walk(dir_root):
for file in files:
if 'to_so.py' in file:
continue
if 'main.py' in file:
continue
if os.path.splitext(file)[1] in ['.c', '.py', '.pyc', '.o']:
_path = os.path.join(root, file) # 使用 os.path.join 生成路径
os.remove(_path)
def py_to_so():
project_dir = './'
res_py_file_list = get_all_py_files(project_dir)
print("Files to compile:", res_py_file_list) # 调试输出
build_dir = './'
build_tmp_dir = './'
setup(ext_modules=cythonize(res_py_file_list), script_args=["build_ext", "-b", build_dir, "-t", build_tmp_dir])
# 清除文件
clean_c_file(project_dir)
if __name__ == '__main__':
py_to_so()
结果
需要改变python运行环境就复制一份Dockerfile把基础镜像改成想要的架构如docker.io/python:3.11-slim、docker.io/python:3.10-slim、docker.io/python:3.13-slim
评论区