-
由
虚拟的现实创建于12月 25, 2023 需要 2 分钟阅读时间
目标
- Poetry 和 Python 开箱即用,包括项目依赖,不用在启动时额外运行 entrypoint.sh 这类脚本初始化环境。
- 为开发和部署都准备好镜像。
- 使用国内镜像源以加速构建。
Dockerfile
假设你的项目是这样的结构:
.
├── Dockerfile
├── pyproject.toml
├── poetry.lock
├── scripts
└── my_awesome_ai_project
复制下列的内容到你的编辑器中,按你的用例做对应的修改。如果你需要,用法在本文的下一节。
Dockerfile
# syntax=docker/dockerfile:1
# 保留上面这个注释以使用 Docker BuildKit
################################
# PYTHON-BASE
# 准备好所有构建和运行时的环境变量,替换国内软件源。
################################
FROM python:3.9.17-slim as python-base
# Python
ENV PYTHONUNBUFFERED=1 \
# pip
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100 \
\
# Poetry的版本
# https://python-poetry.org/docs/configuration/#using-environment-variables
POETRY_VERSION=1.6.1 \
# Poetry的安装位置
POETRY_HOME="/opt/poetry" \
# 没有用户互动
POETRY_NO_INTERACTION=1 \
# 不要自动创建新的虚拟环境,我们只让Python和Poetry用待会我们自己创建好的,
# 无论是构建还是运行时都是如此。
POETRY_VIRTUALENVS_CREATE=false \
\
# 项目依赖和虚拟环境最后会放在这里
VIRTUAL_ENV="/venv" \
\
# Node.js大版本,如果你不需要可以去掉
NODE_MAJOR=18
# 让系统能够找到Poetry和VIRTUAL_ENV
ENV PATH="$POETRY_HOME/bin:$VIRTUAL_ENV/bin:$PATH"
# 手动创建虚拟环境
RUN python -m venv $VIRTUAL_ENV
# 我们的项目目录,这里我们让Python命令行在以后找依赖时考虑这个目录
WORKDIR /app
ENV PYTHONPATH="/app:$PYTHONPATH"
# Huggingface的权重缓存路径,如果你不需要可以去掉
# https://huggingface.co/docs/transformers/installation?highlight=transformers_cache#caching-models
ENV TRANSFORMERS_CACHE="/opt/transformers_cache/"
# 国内镜像源
RUN sed -i 's/deb.debian.org/mirrors.cloud.tencent.com/g' /etc/apt/sources.list.d/debian.sources && \
pip config set global.index-url https://mirrors.cloud.tencent.com/pypi/simple
################################
# BUILDER-BASE
# 安装和编译依赖
################################
FROM python-base as builder-base
RUN apt-get update && \
apt-get install -y \
apt-transport-https \
gnupg \
ca-certificates \
build-essential \
git \
nano \
curl
# 如果你不需要Node.js,可以去掉这一段
RUN mkdir -p /etc/apt/keyrings && \
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://mirrors.ustc.edu.cn/nodesource/deb/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
apt-get update && apt-get install -y nodejs && \
npm config -L global set registry http://mirrors.cloud.tencent.com/npm/
# 安装poetry - 会依赖 $POETRY_VERSION & $POETRY_HOME
# --mount 参数会提示 buildx 缓存 /root/.cache 以加速下一次构建
RUN --mount=type=cache,target=/root/.cache \
curl -sSL https://install.python-poetry.org | python -
# 开始安装依赖,注意 /app 目录下的内容在后面其实会被覆盖掉
WORKDIR /app
COPY poetry.lock pyproject.toml ./
COPY scripts scripts/
COPY my_awesome_ai_project/ my_awesome_ai_project/
# 安装项目运行依赖到VIRTUAL_ENV目录中
RUN --mount=type=cache,target=/root/.cache \
poetry install --no-root --only main
# 预载Huggingface模型权重,这里作为例子,按你的用例修改
RUN poetry run python scripts/bootstrap.py
# 编译C依赖,这里作为例子,按你的用例修改
RUN --mount=type=cache,target=/app/scripts/vendor \
poetry run python scripts/build-c-denpendencies.py && \
cp scripts/lib/*.so /usr/lib
################################
# DEVELOPMENT
# 本地开发和CI测试用的镜像
################################
FROM builder-base as development
WORKDIR /app
# 安装测试和lint所用的依赖
# 运行时依赖已经安装过了,所以这里会比较快
RUN --mount=type=cache,target=/root/.cache \
poetry install --no-root --with test,lint
# 要暴露的端口,按你的用例修改
EXPOSE 8080
CMD ["bash"]
################################
# PRODUCTION
# 生产用的镜像
################################
FROM python-base as production
# 根证书,你可能还会想加上时区信息
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates && \
apt-get clean
# 拷贝已经构建好的 Poetry + venv
COPY --from=builder-base $POETRY_HOME $POETRY_HOME
COPY --from=builder-base $VIRTUAL_ENV $VIRTUAL_ENV
# 拷贝已经构建好的C依赖,这里作为例子,按你的用例修改
COPY --from=builder-base /app/scripts/lib/*.so /usr/lib
# 拷贝预载的模型权重,这里作为例子,按你的用例修改
COPY --from=builder-base $TRANSFORMERS_CACHE $TRANSFORMERS_CACHE
# 拷贝程序
WORKDIR /app
COPY poetry.lock pyproject.toml ./
COPY my_awesome_ai_project/ my_awesome_ai_project/
EXPOSE 8080
CMD ["python", "my_awesome_ai_project/app.py"]
用法
构建生产用的镜像:
docker build --progress plain -t registry.example.com/project/production .
构建开发和测试用的镜像:
docker build --progress plain -t registry.example.com/project/dev --target development .
测试用的镜像可以作为CI运行的环境,将程序挂载到容器中,这能大幅缩短CI时间。
原理
VIRTUAL_ENV 让 Python 和 Poetry 知道我们在虚拟环境中,好让它们查找和安装依赖。
PYTHONPATH 让 Python 考虑你在 /app 中存放的,自己编写的包。
对PATH修改使得我们可以直接调用在 VIRTUAL_ENV 当中安装的可执行依赖。
生产和开发的镜像是同源的,它们可以复用大部分的镜像层,这提升了镜像构建和存储的效率。
参考资料
- 无标签
0 评论