如何在Docker环境中正确安装配置与使用Poetry
以下都是生产环境踩坑攒的实操方案,没有冗余套话:
1. Poetry安装方式选择
不推荐直接用系统自带pip全局安装Poetry。
这种方式看起来省事,实际上Poetry的运行依赖会直接装到系统Python的包目录里,很容易和基础镜像预装的Python包产生版本冲突,最常见的就是装完跑poetry命令直接抛ImportError,查半天才能定位到问题,纯纯浪费时间。
生产环境最稳妥的方式是用官方安装脚本,指定独立安装路径,完全不碰系统Python的依赖目录,Dockerfile里的写法参考:
FROM python:3.11-slim # 安装脚本依赖curl,装完直接清掉减小镜像体积 RUN apt-get update && apt-get install -y --no-install-recommends curl \ # 调用官方安装脚本,指定独立安装路径、固定Poetry版本 && curl -sSL 官方安装脚本入口 | POETRY_HOME=/opt/poetry POETRY_VERSION=1.8.3 python3 - \ # 软链到PATH目录保证全局可调用 && ln -s /opt/poetry/bin/poetry /usr/local/bin/poetry \ && apt-get purge -y --auto-remove curl \ && rm -rf /var/lib/apt/lists/*
如果你的基础镜像已经预装了pipx,用pipx install poetry==1.8.3也可以,本质也是给Poetry创建独立运行环境,只是会额外装pipx,镜像体积会稍大一点。
2. Poetry版本选择
别图新用latest版本,也别写模糊的版本范围,就守两个原则:
- 镜像里的Poetry版本和你本地开发用的版本完全一致,避免poetry.lock格式不兼容,导致装出来的依赖和本地测试的版本对不上,甚至直接安装失败
- 选发布满3个月、没有公开阻断性bug的稳定版,比如目前生产环境验证过最稳的是1.7.x、1.8.x系列,刚发布的大版本别着急上,之前1.2、1.9刚发的时候都出过和Docker层缓存不兼容、依赖解析异常的问题,踩坑的人非常多。
3. 容器内虚拟环境配置
直接关掉Poetry自动创建虚拟环境的配置,完全不需要在容器里用虚拟环境。
容器本身就是做环境隔离的,一个容器里只跑这一个Python应用,再套一层虚拟环境纯属多余,不仅会增加路径排查成本(找解释器、找装的包都要多进一层目录),还会破坏Docker的层缓存机制,拖慢构建速度。
装完Poetry直接执行一行配置就行:
RUN poetry config virtualenvs.create false
后续装依赖直接用poetry install --no-root --only main即可,--no-root是避免把当前项目装成可编辑包占空间,--only main是只装生产依赖、跳过开发依赖组;如果是1.7之前的老版本Poetry,把--only main换成--no-dev效果一致。
实操避坑提示
- 写Dockerfile的时候,先复制
pyproject.toml和poetry.lock两个文件,单独执行依赖安装步骤,再复制剩下的业务代码,这样依赖没变更的时候Docker会直接用缓存层,不用每次构建都重新解析安装依赖,构建速度能快好几倍,写法参考:WORKDIR /app COPY pyproject.toml poetry.lock ./ RUN poetry install --no-root --only main COPY . . - 不要在容器运行时用
poetry add临时装包,所有依赖都要在本地开发阶段写入lock文件,构建镜像时一次性安装,保证镜像的不可变性。 - 用多阶段构建的话,只在构建阶段装Poetry,最终运行阶段直接把构建阶段装好依赖的site-packages目录拷贝过去就行,运行镜像里连Poetry都不用装,镜像体积能缩小一半以上,也更安全。
内容的提问来源于stack exchange,提问作者Soof Golan

