- 由 虚拟的现实创建于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 当中安装的可执行依赖。
生产和开发的镜像是同源的,它们可以复用大部分的镜像层,这提升了镜像构建和存储的效率。
参考资料
- 无标签
添加评论