如何在Dockerfile中通过Poetry安装仅CPU版PyTorch以缩减生产环境容器体积?
作为Docker和容器化的新手,既要搞定CPU版PyTorch的安装,又要压缩容器体积,其实可以从依赖配置和Dockerfile优化两个方向入手,结合你现有的多阶段构建方案,我给你整理了具体的实现步骤:
一、正确配置Poetry安装CPU版PyTorch
PyTorch的CPU版本需要从官方专用源拉取,直接用默认PyPI源可能会下载带CUDA的版本(或找不到对应包),你可以通过两种方式处理:
方式1:在pyproject.toml中预配置依赖和源
这种方式更规范,能让依赖管理更清晰:
- 打开你的
pyproject.toml,添加PyTorch的CPU专用源:
[[tool.poetry.source]] name = "pytorch-cpu" url = "https://download.pytorch.org/whl/cpu"
- 在
[tool.poetry.dependencies]区块中添加CPU版PyTorch和TorchVision(替换成你需要的版本号):
torch = { version = "2.0.1", source = "pytorch-cpu" } torchvision = { version = "0.15.2", source = "pytorch-cpu" }
这样后续poetry install时就会自动从CPU源拉取对应包,不需要额外指定参数。
方式2:在Dockerfile中直接执行Poetry添加命令
如果你更倾向于在Docker构建过程中临时添加,可以在build阶段(或你安装依赖的阶段)加入以下命令:
RUN poetry add torch torchvision --source pytorch-cpu -c https://download.pytorch.org/whl/cpu
注意:现在PyTorch官方已不再使用
pytorch-cpu这种旧包名,统一用torch,通过源区分CPU/CUDA版本,所以更推荐用方式1配置源,避免后续版本兼容问题。
二、优化Dockerfile缩减容器体积
你的Dockerfile已经用了多阶段构建,这是压缩体积的好基础,再结合以下优化点可以进一步减小镜像大小:
1. 精简基础镜像与系统依赖
- 保持使用
python:3.7-slim作为基础镜像(比alpine更兼容Python生态,避免依赖编译问题) - 安装系统依赖时,只装必要的包,并且安装后立刻清理APT缓存,减少冗余:
RUN apt-get update -y \ && apt-get install -y --no-install-recommends gcc curl wget \ && rm -rf /var/lib/apt/lists/*
把
gcc和其他工具合并到一个apt-get install命令里,减少镜像层,同时清理缓存避免无用文件残留。
2. 利用Docker层缓存优化依赖安装
在build阶段,先复制pyproject.toml和poetry.lock(如果存在),再执行poetry install,这样只有当依赖文件变化时才会重新安装依赖,加快构建速度同时减少层的大小:
FROM base as build # 先复制依赖配置文件,利用缓存 COPY pyproject.toml poetry.lock* $ROOT/ # 安装生产依赖并清理缓存 RUN poetry config experimental.new-installer false \ && poetry install --no-dev \ && rm -rf $POETRY_HOME/.cache /root/.cache/pip # 再复制项目代码 COPY . . # 后续的AWS和模型下载步骤...
3. 清理构建过程中的冗余文件
在每个阶段完成后,清理不必要的文件:
- 删除Poetry的安装脚本:
RUN rm get-poetry.py - 合并模型下载命令,减少镜像层并清理wget缓存:
RUN mkdir -p $ROOT/my_proj/bert-base-cased && cd $ROOT/my_proj/bert-base-cased \ && wget -q https://huggingface.co/bert-base-cased/resolve/main/config.json \ && wget -q https://huggingface.co/bert-base-cased/resolve/main/tokenizer.json \ && wget -q https://huggingface.co/bert-base-cased/resolve/main/tokenizer_config.json
用
-q参数让wget静默输出,避免日志文件占用空间。
4. 生产阶段只复制必要文件
在production阶段,只复制运行所需的文件:虚拟环境、项目代码、配置文件,不要复制构建过程中的临时文件(比如dist目录、安装脚本等),你现有的配置已经做得不错,可以保持。
修改后的完整Dockerfile示例
结合上面的优化点,调整后的Dockerfile大概是这样:
FROM python:3.7-slim as base RUN apt-get update -y \ && apt-get install -y --no-install-recommends gcc curl wget \ && rm -rf /var/lib/apt/lists/* ENV ROOT /home/worker/python/my_proj WORKDIR $ROOT # 环境变量配置 ARG ATLASSIAN_TOKEN ARG POETRY_HTTP_BASIC_AZURE_PASSWORD ARG ACCESS_KEY ENV AWS_ACCESS_KEY_ID=$ACCESS_KEY ARG SECRET_KEY ENV AWS_SECRET_ACCESS_KEY=$SECRET_KEY ARG REPO ENV REPO_URL=$REPO ENV PYPIRC_PATH=$ROOT/.pypirc ENV \ PYTHONFAULTHANDLER=1 \ POETRY_VERSION=1.1.4 \ POETRY_HOME=/etc/poetry \ XDG_CACHE_HOME=/home/worker/.cache \ POETRY_VIRTUALENVS_IN_PROJECT=true \ MPLCONFIGDIR=/home/worker/matplotlib \ PATH=/home/worker/python/my_proj/.venv/bin:/usr/local/bin:/etc/poetry/bin:$PATH # 安装Poetry并清理安装脚本 ADD https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py ./ RUN python get-poetry.py \ && chmod +x /etc/poetry/bin/poetry \ && rm get-poetry.py RUN --mount=type=cache,target=/root/.cache pip install --no-cache-dir twine keyring artifacts-keyring FROM base as ws ARG WS_APIKEY ARG WS_PROJECTVERSION= ARG WS_PROJECTNAME=workers-python-my_proj ARG WS_PRODUCTNAME=HALO COPY --chown=worker:worker . . RUN --mount=type=cache,uid=1000,target=/home/worker/.cache poetry install --no-dev COPY --from=openjdk:15-slim-buster /usr/local/openjdk-15 /usr/local/openjdk-15 ENV JAVA_HOME /usr/local/openjdk-15 ENV PATH $JAVA_HOME/bin:$PATH RUN --mount=type=cache,uid=1000,target=/home/worker/.cache ./wss_agent.sh FROM base as test COPY . . RUN poetry config experimental.new-installer false RUN poetry install RUN cd my_proj && poetry run invoke deployconfluence_server_pass=$ATLASSIAN_TOKEN FROM base as package COPY . . RUN poetry build RUN python -m pip install --upgrade pip && \ pip install --no-cache-dir twine keyring artifacts-keyring && \ twine upload -r $REPO_URL --config-file $PYPIRC_PATH dist/* --skip-existing FROM base as build # 优化依赖安装顺序,利用缓存 COPY pyproject.toml poetry.lock* $ROOT/ RUN poetry config experimental.new-installer false \ && poetry install --no-dev \ && rm -rf $POETRY_HOME/.cache /root/.cache/pip # 复制项目代码 COPY . . # 安装AWS CLI并清理缓存 RUN pip3 install --no-cache-dir --upgrade awscli # 下载模型并合并命令 RUN aws s3 cp s3://....tar.gz $ROOT/my_proj \ && mkdir -p $ROOT/my_proj/bert-base-cased && cd $ROOT/my_proj/bert-base-cased \ && wget -q https://huggingface.co/bert-base-cased/resolve/main/config.json \ && wget -q https://huggingface.co/bert-base-cased/resolve/main/tokenizer.json \ && wget -q https://huggingface.co/bert-base-cased/resolve/main/tokenizer_config.json FROM python:3.7-slim as production ENV ROOT=/home/worker/python/my_proj \ VIRTUAL_ENV=/home/worker/python/my_proj/.venv\ PATH=/home/worker/python/my_proj/.venv/bin:/home/worker/python/my_proj:$PATH # 只复制必要文件 COPY --from=build $ROOT/.venv $ROOT/.venv COPY --from=build $ROOT/my_proj $ROOT/my_proj COPY --from=build $ROOT/pyproject.toml /home/worker/python/ WORKDIR $ROOT ENV PYTHONPATH=$ROOT:/home/worker/python/ ENTRYPOINT [ "primary_worker", "--mongo" ]
这样调整后,既确保了CPU版PyTorch的正确安装,又通过减少冗余文件、优化层缓存等方式显著压缩了容器体积。
内容的提问来源于stack exchange,提问作者user16341274

