Python 工程构建部署


Docker 通过容器化技术为服务提供了环境隔离且便捷化的服务管理,今天就让我们一起来看看如何将 Python 工程打包为 Docker Image 并实现服务运行。

1. 镜像构建

FastAPI 项目为例,其中 src 为源码目录,requirements.txt 为依赖配置,如下图所示。

将上述工程源码完整拷贝至服务器目录,并在同级新建 Dockerfile 文件得到下图结构。

接下来便可编写 Dockerfile 进行镜像构建,文件内容如下:

FROM python:3.11-slim

WORKDIR /app

# 系统依赖
RUN apt-get update && apt-get install -y \
    gcc g++ libstdc++6 \
    && rm -rf /var/lib/apt/lists/*

# 依赖安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 源码拷贝
COPY src ./src

# 环境变量
ENV PYTHONPATH=/app/src

# 暴露端口
EXPOSE 8091

# 启动命令
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8091"]

其中 COPY 用于复制宿主机文件或目录至构建好的镜像中,其命令格式如下:

COPY <容器中目录> <待拷贝目标>

需特别注意 COPY 命令并不支持读取服务器绝对路径,而是根据 Dockerfile 文件目录作为起始路径进行读取,因此需要将待拷贝内容置于 Dockerfile 同级下。

如下述配置通过绝对路径 /home/data/python/src 复制目录在编译时将失败。

# 非法,不支持绝对路径
COPY src /home/data/python/src

2. 离线编译

通过上述虽可实现镜像构建,但注意到每次构建镜像都会触发 requirements.txt 依赖的在线下载。而对应绝多数服务更新中往往仅涉及代码变更,每次都触发依赖下载都将增加服务构建耗时,显然并不合理。

因此,在更多的场景下我们往往会采取离线编译的方式,即使用已经存在依赖文件 .whl 进行构建。

但使用离线构建需注意一点,工程中使用的部分依赖可能并不直接提供 .whl 文件而需要我们自行构建。

此时则需要使用 wheel 工具手动编译依赖,通过下述命令下载编译工具。

pip install build wheel setuptools

完成后以 langdetect 工具库为例,通过 pip download 下载指定版本依赖得到 .tar.gz 文件,解压后进入目录通过对应命令编辑,完成后便会在 dist/ 目录下生成 .whl 依赖文件。

# 下载依赖
pip download langdetect==1.0.9

# 依赖解包
tar xf langdetect-1.0.9.tar.gz

# 依赖编译
cd langdetect-1.0.9
python -m build --wheel

而对应提供了 .whl 的依赖而言,则可直接根据 requirements.txt 下载。

如下则通过 requirements.txt 下载依赖并统一输出至 wheelhouse 目录。

pip download -r requirements.txt -d wheelhouse

上述步骤完成后回到 Dockerfile 中,替换之前的 pip install 命令,通过 --find-links=/wheelhouse 关联本地依赖文件,在构建时则不再触发在线依赖下载。

通过此方式,避免了每次重复依赖的网络下载开销,极大提供了服务构建效率。

FROM python:3.11-slim

WORKDIR /app

RUN apt-get update && apt-get install -y \
    gcc g++ libstdc++6 \
    && rm -rf /var/lib/apt/lists/*

# 依赖安装
COPY wheelhouse /wheelhouse
COPY requirements.txt .
RUN pip install --no-index --find-links=/wheelhouse -r requirements.txt

COPY src ./src

ENV PYTHONPATH=/app/src

EXPOSE 8091
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8091"]

3. 服务运行

准备好 Dockerfile 后通过 build 构建镜像,完成后可通过 docker images 查询已有镜像信息。

docker build -t test-fastapi:1.0 .

镜像文件构建完毕之后便可同 docker run 启动服务,这里便不再过多赘述。

docker run -d \
-name test-fastapi \
-p 8091:8091 \
test-fastapi:1.0

文章作者: 烽火戏诸诸诸侯
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 烽火戏诸诸诸侯 !
  目录