推荐设置的环境变量

构建 Python Docker 镜像时,建议始终设置以下两个环境变量:

1
2
3
4
# 防止 python 将 pyc 文件写入硬盘
ENV PYTHONDONTWRITEBYTECODE 1
# 防止 python 缓冲 (buffering) stdout 和 stderr,以便更容易地进行容器日志记录
ENV PYTHONUNBUFFERED 1

不建议使用 ENV DEBUG 0 这类环境变量,没有必要。

使用非 root 用户运行容器进程

出于安全考虑,推荐运行 Python 程序前,创建非 root 用户并切换到该用户:

1
2
3
# 创建一个具有明确 UID 的非 root 用户,并增加访问 /app 文件夹的权限
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser

使用 .dockerignore 排除无关文件

在项目根目录创建 .dockerignore 文件,排除不需要进入镜像的文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
**/__pycache__
**/*venv
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
*.db
.python-version
LICENSE
README.md

不建议使用 Alpine 作为 Python 的基础镜像

这是一个常见的误区。很多人选择 Alpine 是因为它体积小,但实际上用 Alpine 构建 Python 镜像反而可能遇到更多问题,最终镜像甚至可能更大。

核心原因:musl vs glibc

大多数 Linux 发行版使用 GNU 版本(glibc)的标准 C 库,几乎每个 C 程序都需要这个库,包括 Python。但 Alpine Linux 使用的是 musl,这导致 Alpine 禁用了 Linux wheel 支持

具体问题

  • 缺少大量依赖:CPython 运行时依赖、openssl、libffi、gcc、数据库驱动、pip 等都需要额外安装
  • 编译时间长:大多数 Python 包在 PyPI 上都提供了二进制 wheel,能大大加快安装时间。但 Alpine 禁用了 wheel 支持,意味着你需要编译每个 Python 包中的所有 C 代码
  • 构建更耗时:缺少预编译的 wheel,每次 pip install 都要从源码编译
  • 镜像可能更大:为了编译需要安装大量开发工具包,最终镜像反而比 slim 版本更大

如果确实需要使用 Alpine,pip 安装前需要先安装完整的编译依赖:

1
2
3
4
5
6
RUN set -eux \
&& apk add --no-cache --virtual .build-deps build-base \
openssl-dev libffi-dev gcc musl-dev python3-dev \
&& pip install --upgrade pip setuptools wheel \
&& pip install --upgrade -r /app/requirements.txt \
&& rm -rf /root/.cache/pip

如果在 Alpine 上遇到具体的包安装问题,可以参考这篇:Dockerfile中Alpine安装依赖包失败总结

建议使用官方的 Python Slim 镜像

推荐使用 Docker Hub 官方的 Python Slim 镜像作为基础镜像:

  • 镜像地址:https://hub.docker.com/_/python
  • 推荐标签:python:X.Y-slim 或更具体的 python:X.Y-slim-bullseye(基于更新的 Debian 版本,安全性更好)

为什么选择 Slim

  • 稳定性:基于 Debian,经过充分测试
  • 安全升级更及时:官方维护,安全补丁响应快
  • 依赖更全:包含运行 Python 所需的最小包
  • Python 版本升级更及时:第一时间获取最新 Python 版本
  • 镜像体积小:不包含默认标签中的常用包,只保留运行 Python 的必要组件

一般情况下不需要多阶段构建

Python 不像 Golang 可以把所有依赖打成单一二进制包,也不像 Java 可以在 JDK 上构建、在 JRE 上运行。Python 复杂而散落的依赖关系,在多阶段构建时反而会增加复杂度。

可以考虑多阶段构建的特殊情况:

  • 构建阶段需要安装编译器(如 gcc),运行时不需要
  • Python 项目用到了其他语言代码(如 C/C++/Rust)

Dockerfile 中 pip 编写建议

使用 pip 安装依赖时,添加 --no-cache-dir 减少镜像体积:

1
2
3
# 安装 pip 依赖
COPY requirements.txt .
RUN python -m pip install --no-cache-dir --upgrade -r requirements.txt

Dockerfile 完整示例

推荐:Slim 版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
FROM python:3.10-slim

LABEL maintainer="ssw"

EXPOSE 8000

# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE=1

# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED=1

# Install pip requirements
COPY requirements.txt .
RUN python -m pip install --no-cache-dir --upgrade -r requirements.txt

WORKDIR /app
COPY . /app

# Creates a non-root user with an explicit UID and adds permission to access the /app folder
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser

CMD ["uvicorn", "shortener_app.main:app", "--host", "0.0.0.0"]

不推荐:Alpine 版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
FROM python:3.10-alpine

LABEL maintainer="ssw"

EXPOSE 8000

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# Install pip requirements(需要额外安装编译依赖)
COPY requirements.txt .
RUN set -eux \
&& apk add --no-cache --virtual .build-deps build-base \
openssl-dev libffi-dev gcc musl-dev python3-dev \
&& pip install --upgrade pip setuptools wheel \
&& pip install --upgrade -r /app/requirements.txt \
&& rm -rf /root/.cache/pip

WORKDIR /app
COPY . /app

RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser

CMD ["uvicorn", "shortener_app.main:app", "--host", "0.0.0.0"]

总结

实践 建议
基础镜像 使用 python:X.Y-slim,避免 Alpine
环境变量 设置 PYTHONDONTWRITEBYTECODE=1PYTHONUNBUFFERED=1
安全 创建非 root 用户运行容器进程
pip 使用 --no-cache-dir 减少镜像体积
.dockerignore 排除 __pycache__.gitvenv 等无关文件
多阶段构建 一般不需要,除非涉及 C/C++/Rust 编译

本站由 sswfive 使用 Stellar 1.42.0 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站总访问量