使用 Docker 构建容器
如果您想将 Python 代码放入容器中,您可能有一些服务器代码没有提交到 PyPI 或其他注册中心。如果是这样,请继续阅读。否则,跳过 下一节。
本指南要求您熟悉 Docker 和 Dockerfile。
从源代码创建容器
-
确保您的项目已设置为 虚拟项目。这意味着您不能安装它,它也不会将自己标记为依赖项。如果您需要您的项目可安装,请转到 下一节。
- 您的
pyproject.toml
应该在[tool.rye]
部分包含virtual = true
。如果没有,请添加它并运行rye sync
。 - 如果您只是在设置项目,请运行
rye init --virtual
而不是rye init
。
- 您的
-
在您的项目根目录中创建一个包含以下内容的
Dockerfile
,使用uv
FROM python:slim RUN pip install uv WORKDIR /app COPY requirements.lock ./ RUN uv pip install --no-cache --system -r requirements.lock COPY src . CMD python main.py
或者,使用
pip
FROM python:slim WORKDIR /app COPY requirements.lock ./ RUN PYTHONDONTWRITEBYTECODE=1 pip install --no-cache-dir -r requirements.lock COPY src . CMD python main.py
-
现在您可以像这样构建您的镜像
docker build .
Dockerfile 调整
本指南中的 Dockerfile
是示例。您可能需要进行一些调整
- 命令 (
CMD python src/main.py
) 应该指向您的脚本。 - 调整基本镜像 (
FROM python:slim
) - 优先使用与您的
.python-version
文件中版本匹配的标记版本,例如FROM python:3.12.0-slim
。 -slim
变体通常是镜像大小和兼容性之间的一个很好的折衷方案,对于大多数工作负载来说应该可以正常工作。但是,您也可以使用-alpine
创建更小的镜像(但存在潜在的兼容性问题),或者使用不带后缀的镜像,这些镜像包含更多系统工具。- 如果您需要其他系统包,请在复制源代码之前安装它们,即在
COPY src .
行之前。在使用基于 Debian 的镜像(即-slim
或不带后缀的变体)时,这可能看起来像这样
RUN apt-get update \
&& apt-get install -y --no-install-recommends some-dependency another-dependency \
&& rm -rf /var/lib/apt/lists/*
从 Python 包创建容器
如果您的代码是一个可安装的包,建议您先构建它,然后在 Docker 镜像中安装它。这样,您可以确保镜像与用户安装完全相同。
使用 uv
的 Dockerfile
示例可能看起来像这样
FROM python:slim
RUN pip install uv
RUN --mount=source=dist,target=/dist uv pip install --no-cache /dist/*.whl
CMD python -m my_package
要构建 Docker 镜像,您必须先构建您的轮子,像这样
rye build --wheel --clean
docker build . --tag your-image-name
请注意,这种方法将您的依赖项和代码捆绑在一个层中。这可能对性能有利,但它也意味着每次镜像构建都会重新安装所有依赖项,并且不同的版本不会共享依赖项的磁盘空间。
解释
Rye 的锁定文件标准是 pip
的 requirements.txt
格式(由 uv
使用),因此您实际上不需要在容器中使用 rye
即可安装依赖项。这使得 Dockerfile 变得更简单,并且如果需要小镜像,则可以避免多阶段构建的必要性。
分别传递给 pip
和 uv
的 --no-cache-dir
和 --no-cache
参数通过不写入任何临时文件来使镜像更小。虽然缓存可以加快后续构建速度,但在容器中,镜像只构建一次并使用多次,因此缓存不是必需的。
类似地,设置了 PYTHONDONTWRITEBYTECODE=1
环境变量以避免写入 .pyc
文件,这些文件在容器中不需要。(uv
默认情况下会跳过写入 .pyc
文件。)