docker-build
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDocker Build for Python/FastAPI Applications
Python/FastAPI应用的Docker构建
Overview
概述
Containerize Python and FastAPI applications using Docker with
production-grade multi-stage builds, layer caching, security hardening, and
Docker Compose orchestration. All patterns target Python 3.12+, use for
dependency management, and follow the principle of minimal, reproducible
images.
uvRefer to the asset templates bundled with this skill for ready-to-use
starting points:
- -- production multi-stage Dockerfile
assets/Dockerfile.fastapi - -- development Dockerfile with hot reload
assets/Dockerfile.dev - -- Compose stack with PostgreSQL and Redis
assets/docker-compose.yml - -- ignore rules for lean build contexts
assets/.dockerignore
使用Docker对Python和FastAPI应用进行容器化,采用生产级别的多阶段构建、层缓存、安全加固以及Docker Compose编排。所有模式均针对Python 3.12+版本,使用进行依赖管理,并遵循最小化、可复现镜像的原则。
uv参考此技能附带的资产模板,获取可直接使用的起点:
- -- 生产环境多阶段Dockerfile
assets/Dockerfile.fastapi - -- 带热重载的开发环境Dockerfile
assets/Dockerfile.dev - -- 包含PostgreSQL和Redis的Compose栈
assets/docker-compose.yml - -- 精简构建上下文的忽略规则
assets/.dockerignore
Base Image Selection
基础镜像选择
Choose the base image according to the deployment target and dependency
requirements.
根据部署目标和依赖要求选择基础镜像。
python:3.12-slim (recommended)
python:3.12-slim(推荐)
The default choice for most FastAPI projects. Based on Debian Bookworm with a
minimal package set. Binary wheels from PyPI install without issues, and
system libraries such as can be added via .
libpqapt-getdockerfile
FROM python:3.12-slim AS base大多数FastAPI项目的默认选择。基于Debian Bookworm,包含最小化的软件包集合。PyPI的二进制wheel可顺利安装,可通过添加等系统库。
apt-getlibpqdockerfile
FROM python:3.12-slim AS basepython:3.12-alpine
python:3.12-alpine
Smaller download size, but Alpine uses musl libc. Packages with C extensions
(e.g., , , ) often fail to install or require
building from source, negating the size advantage. Avoid unless the
dependency tree is pure Python.
psycopg2numpypandas下载体积更小,但Alpine使用musl libc。带有C扩展的软件包(如、、)通常安装失败或需要从源码构建,抵消了体积优势。除非依赖树全部为纯Python,否则避免使用。
psycopg2numpypandasghcr.io/astral-sh/uv:python3.12-bookworm-slim
ghcr.io/astral-sh/uv:python3.12-bookworm-slim
Ships with pre-installed. Useful when the build should not fetch
at build time. The image is Debian-based and behaves like
otherwise.
uvuvpython:3.12-slimdockerfile
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder预安装了。适用于构建时无需拉取的场景。该镜像基于Debian,其他行为与一致。
uvuvpython:3.12-slimdockerfile
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builderMulti-Stage Build Pattern
多阶段构建模式
Separate dependency installation from the final runtime image to keep the
production image small and free of build tools.
将依赖安装与最终运行时镜像分离,以保持生产镜像体积小巧且不含构建工具。
Stage 1 -- Builder
阶段1 -- 构建器
Install , copy only the dependency manifests, and resolve/install
dependencies into a virtual environment. This stage may contain compilers and
header packages that must not ship in production.
uvdockerfile
FROM python:3.12-slim AS builder
COPY /uv /usr/local/bin/uv
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project
COPY . .
RUN uv sync --frozen --no-dev安装,仅复制依赖清单,并将依赖解析/安装到虚拟环境中。此阶段可包含编译器和头文件包,但这些不得随生产镜像发布。
uvdockerfile
FROM python:3.12-slim AS builder
COPY /uv /usr/local/bin/uv
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project
COPY . .
RUN uv sync --frozen --no-devStage 2 -- Runtime
阶段2 -- 运行时
Start from a clean slim image, copy only the virtual environment and
application source from the builder, create a non-root user, and declare the
entrypoint.
dockerfile
FROM python:3.12-slim AS runtime
WORKDIR /app
COPY /app/.venv /app/.venv
COPY /app/src /app/src
ENV PATH="/app/.venv/bin:$PATH"
RUN useradd --create-home --shell /bin/bash appuser
USER appuser
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]从干净的slim镜像开始,仅从构建器复制虚拟环境和应用源码,创建非root用户,并声明入口点。
dockerfile
FROM python:3.12-slim AS runtime
WORKDIR /app
COPY /app/.venv /app/.venv
COPY /app/src /app/src
ENV PATH="/app/.venv/bin:$PATH"
RUN useradd --create-home --shell /bin/bash appuser
USER appuser
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]uv Integration in Docker
Docker中的uv集成
Installing uv
安装uv
The fastest method is a static binary copy from the official image:
dockerfile
COPY /uv /usr/local/bin/uvAlternatively, install via pip (slower, but works on any base):
dockerfile
RUN pip install --no-cache-dir uv最快的方法是从官方镜像复制静态二进制文件:
dockerfile
COPY /uv /usr/local/bin/uv或者通过pip安装(速度较慢,但可在任何基础镜像上运行):
dockerfile
RUN pip install --no-cache-dir uvDependency Resolution
依赖解析
Always pass to inside Docker so that the lockfile is
used as-is without resolution. This guarantees reproducible builds.
--frozenuv syncdockerfile
RUN uv sync --frozen --no-devFor uv dependency management outside of Docker, consult the skill.
uv在Docker内部执行时,始终传递参数,以便直接使用锁定文件而不进行重新解析。这可确保构建的可复现性。
uv sync--frozendockerfile
RUN uv sync --frozen --no-dev关于Docker之外的uv依赖管理,请参考技能文档。
uvLayer Ordering for Cache Efficiency
缓存效率的层顺序
Docker caches each layer. When a layer changes, every subsequent layer is
rebuilt. Order instructions from least to most frequently changing:
- Base image and system packages
- Copy dependency manifests (,
pyproject.toml)uv.lock - Install dependencies ()
uv sync - Copy application source code
- Any final build steps
dockerfile
undefinedDocker会缓存每个层。当某一层发生变化时,后续所有层都将重新构建。按变更频率从低到高排列指令:
- 基础镜像和系统软件包
- 复制依赖清单(、
pyproject.toml)uv.lock - 安装依赖()
uv sync - 复制应用源码
- 任何最终构建步骤
dockerfile
undefinedStep 2 -- manifests change infrequently
步骤2 -- 清单变更频率低
COPY pyproject.toml uv.lock ./
COPY pyproject.toml uv.lock ./
Step 3 -- re-runs only when manifests change
步骤3 -- 仅在清单变更时重新运行
RUN uv sync --frozen --no-dev --no-install-project
RUN uv sync --frozen --no-dev --no-install-project
Step 4 -- changes on every code edit
步骤4 -- 每次代码编辑都会变更
COPY src/ src/
This ordering ensures that dependency installation is cached across most code
changes, drastically reducing rebuild times.
---COPY src/ src/
此顺序确保依赖安装在大多数代码变更时都能被缓存,大幅缩短重建时间。
---Security Hardening
安全加固
Non-Root User
非Root用户
Never run the application as root inside the container. Create a dedicated
user and switch to it before .
CMDdockerfile
RUN useradd --create-home --shell /bin/bash appuser
USER appuserFor stricter security, use a numeric UID and no login shell:
dockerfile
RUN adduser --system --uid 1001 --no-create-home appuser
USER 1001永远不要在容器内以root身份运行应用。创建专用用户,并在之前切换到该用户。
CMDdockerfile
RUN useradd --create-home --shell /bin/bash appuser
USER appuser如需更严格的安全设置,可使用数字UID且不设置登录shell:
dockerfile
RUN adduser --system --uid 1001 --no-create-home appuser
USER 1001Minimal Packages
最小化软件包
Do not install editors, debug tools, or documentation packages in the
production image. If build-time packages are necessary (e.g., ,
), install them only in the builder stage.
gcclibpq-dev不要在生产镜像中安装编辑器、调试工具或文档软件包。如果构建时需要某些软件包(如、),仅在构建器阶段安装它们。
gcclibpq-dev.dockerignore
.dockerignore
Exclude files that must not enter the build context: version control
metadata, local environment files, test suites, caches, and documentation.
See for a comprehensive template.
assets/.dockerignore排除不得进入构建上下文的文件:版本控制元数据、本地环境文件、测试套件、缓存和文档。参考获取全面的模板。
assets/.dockerignorePin Image Digests in CI
在CI中固定镜像摘要
For reproducible CI builds, pin the base image to a digest:
dockerfile
FROM python:3.12-slim@sha256:<digest> AS builder为实现可复现的CI构建,将基础镜像固定到具体的摘要值:
dockerfile
FROM python:3.12-slim@sha256:<digest> AS builderHEALTHCHECK Instruction
HEALTHCHECK指令
Define a health check so orchestrators (Docker Swarm, Compose, ECS) can
detect unresponsive containers and restart them automatically.
dockerfile
HEALTHCHECK \
CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"] || exit 1If is available in the runtime image, prefer the simpler form:
curldockerfile
HEALTHCHECK \
CMD curl -f http://localhost:8000/health || exit 1Ensure the FastAPI application exposes a lightweight endpoint that
returns HTTP 200.
/health定义健康检查,以便编排器(Docker Swarm、Compose、ECS)能够检测无响应的容器并自动重启。
dockerfile
HEALTHCHECK \
CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"] || exit 1如果运行时镜像中包含,可使用更简洁的形式:
curldockerfile
HEALTHCHECK \
CMD curl -f http://localhost:8000/health || exit 1确保FastAPI应用暴露一个轻量级的端点,返回HTTP 200状态码。
/healthEnvironment Variables
环境变量
Set these early in the Dockerfile to influence Python runtime behavior:
dockerfile
undefined在Dockerfile中尽早设置这些变量,以影响Python运行时行为:
dockerfile
undefinedSend stdout/stderr straight to the terminal without buffering
将stdout/stderr直接发送到终端,不进行缓冲
ENV PYTHONUNBUFFERED=1
ENV PYTHONUNBUFFERED=1
Prevent .pyc file creation inside the container
防止在容器内创建.pyc文件
ENV PYTHONDONTWRITEBYTECODE=1
Application-specific variables (database URL, secret keys) should be injected
at runtime via `docker run --env-file` or the Compose `env_file` directive,
never baked into the image.
---ENV PYTHONDONTWRITEBYTECODE=1
应用特定的变量(数据库URL、密钥)应在运行时通过`docker run --env-file`或Compose的`env_file`指令注入,永远不要嵌入到镜像中。
---CMD with Exec Form
执行格式的CMD
Always use the exec form (JSON array) for so that receives
signals directly from Docker and can shut down gracefully.
CMDuvicorndockerfile
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]Avoid the shell form () because it wraps the process in
, which swallows and delays container stops.
CMD uvicorn .../bin/sh -cSIGTERMFor uvicorn production configuration (workers, timeouts, keep-alive),
consult the skill.
uvicorn始终使用执行格式(JSON数组)编写,以便直接接收来自Docker的信号并优雅关闭。
CMDuvicorndockerfile
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]避免使用shell格式(),因为它会将进程包装在中,这会吞噬信号并延迟容器停止。
CMD uvicorn .../bin/sh -cSIGTERM关于uvicorn的生产配置(工作进程、超时、保持连接),请参考技能文档。
uvicornDocker Compose
Docker Compose
Use Docker Compose to orchestrate the application alongside backing services
such as PostgreSQL and Redis. See for a complete
template.
assets/docker-compose.yml使用Docker Compose将应用与PostgreSQL、Redis等后端服务一起编排。参考获取完整模板。
assets/docker-compose.ymlService Definitions
服务定义
yaml
services:
app:
build:
context: .
dockerfile: Dockerfile.fastapi
ports:
- "8000:8000"
env_file:
- .env
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthyyaml
services:
app:
build:
context: .
dockerfile: Dockerfile.fastapi
ports:
- "8000:8000"
env_file:
- .env
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthyHealth Checks in Compose
Compose中的健康检查
Each service should declare a so that with
works correctly.
healthcheckdepends_oncondition: service_healthyyaml
db:
image: postgres:16-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5每个服务都应声明,以便配合正常工作。
healthcheckdepends_oncondition: service_healthyyaml
db:
image: postgres:16-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5Volumes
卷
Persist database data across container recreations:
yaml
volumes:
postgres_data:
redis_data:在容器重新创建时持久化数据库数据:
yaml
volumes:
postgres_data:
redis_data:Networks
网络
Isolate inter-service traffic on a dedicated bridge network:
yaml
networks:
backend:
driver: bridge在专用的桥接网络上隔离服务间通信:
yaml
networks:
backend:
driver: bridgeDevelopment vs Production Dockerfiles
开发与生产Dockerfile对比
Maintain separate Dockerfiles for each environment.
为每个环境维护单独的Dockerfile。
Production (Dockerfile.fastapi
)
Dockerfile.fastapi生产环境(Dockerfile.fastapi
)
Dockerfile.fastapi- Multi-stage build
- dependencies only
--no-dev - Source code copied into the image
- Non-root user, health check, exec-form CMD
- 多阶段构建
- 仅包含依赖
--no-dev - 源码复制到镜像中
- 非root用户、健康检查、执行格式的CMD
Development (Dockerfile.dev
)
Dockerfile.dev开发环境(Dockerfile.dev
)
Dockerfile.dev- Single stage for simplicity
- All dependencies including dev extras (,
pytest, etc.)ruff - Source code mounted via a bind volume -- do not source
COPY - flag on uvicorn for hot reload
--reload
dockerfile
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]Override the production Compose file with a development variant:
yaml
undefined- 单阶段构建,简化流程
- 包含所有依赖,包括开发附加组件(、
pytest等)ruff - 源码通过绑定卷挂载 -- 不要源码
COPY - uvicorn使用标志实现热重载
--reload
dockerfile
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]使用开发变体覆盖生产Compose文件:
yaml
undefineddocker-compose.override.yml
docker-compose.override.yml
services:
app:
build:
dockerfile: Dockerfile.dev
volumes:
- .:/app
---services:
app:
build:
dockerfile: Dockerfile.dev
volumes:
- .:/app
---Build Arguments
构建参数
Use to parameterize the build without creating multiple Dockerfiles.
ARGdockerfile
ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}-slim AS builder
ARG APP_VERSION=0.0.0
LABEL org.opencontainers.image.version=${APP_VERSION}Pass values at build time:
bash
docker build --build-arg PYTHON_VERSION=3.13 --build-arg APP_VERSION=1.2.0 .使用参数化构建,无需创建多个Dockerfile。
ARGdockerfile
ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}-slim AS builder
ARG APP_VERSION=0.0.0
LABEL org.opencontainers.image.version=${APP_VERSION}在构建时传递参数值:
bash
docker build --build-arg PYTHON_VERSION=3.13 --build-arg APP_VERSION=1.2.0 .Volume Mounts for Development
开发环境的卷挂载
Bind-mount the project directory into the container so that file changes on
the host are immediately visible inside the container, enabling uvicorn's
watcher.
--reloadbash
docker run -v "$(pwd)":/app -p 8000:8000 myapp-devIn Compose:
yaml
services:
app:
volumes:
- .:/appAvoid bind-mounting over the directory. If the virtual environment
lives inside the project tree, use an anonymous volume to shadow it:
.venvyaml
volumes:
- .:/app
- /app/.venv将项目目录绑定挂载到容器中,以便主机上的文件变更能立即在容器内生效,启用uvicorn的监视器。
--reloadbash
docker run -v "$(pwd)":/app -p 8000:8000 myapp-dev在Compose中:
yaml
services:
app:
volumes:
- .:/app避免绑定挂载覆盖目录。如果虚拟环境位于项目目录内,使用匿名卷将其隐藏:
.venvyaml
volumes:
- .:/app
- /app/.venvImage Size Reduction Checklist
镜像体积缩减清单
- Use instead of the full
python:3.12-slimimage.python - Apply multi-stage builds; keep compilers in the builder stage only.
- Combine commands where logical to reduce layer count.
RUN - Pass to pip or use
--no-cache-dir(which never caches by default).uv - Remove apt lists after installing system packages:
RUN apt-get update && apt-get install -y --no-install-recommends pkg && rm -rf /var/lib/apt/lists/* - Add a thorough to minimize the build context.
.dockerignore - Compile bytecode at build time () and skip
UV_COMPILE_BYTECODE=1generation at runtime (.pyc).PYTHONDONTWRITEBYTECODE=1
- 使用而非完整的
python:3.12-slim镜像。python - 采用多阶段构建;仅在构建器阶段保留编译器。
- 在合理的情况下合并命令,以减少层数。
RUN - 向pip传递参数,或使用
--no-cache-dir(默认从不缓存)。uv - 安装系统软件包后删除apt列表:
RUN apt-get update && apt-get install -y --no-install-recommends pkg && rm -rf /var/lib/apt/lists/* - 添加完善的以最小化构建上下文。
.dockerignore - 在构建时编译字节码(),并在运行时跳过
UV_COMPILE_BYTECODE=1生成(.pyc)。PYTHONDONTWRITEBYTECODE=1
Multi-Architecture Builds
多架构构建
Build images for multiple platforms using :
docker buildxbash
undefined使用为多个平台构建镜像:
docker buildxbash
undefinedCreate a buildx builder
创建buildx构建器
docker buildx create --name multiarch --use
docker buildx create --name multiarch --use
Build and push for amd64 and arm64
为amd64和arm64构建并推送
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest --push .
When using multi-arch builds, ensure all base images support the target platforms. Avoid architecture-specific binaries in `COPY` instructions.
---docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest --push .
使用多架构构建时,确保所有基础镜像支持目标平台。避免在`COPY`指令中使用特定架构的二进制文件。
---BuildKit Secrets
BuildKit密钥
Mount secrets at build time without baking them into image layers:
dockerfile
undefined在构建时挂载密钥,而不将其嵌入到镜像层中:
dockerfile
undefinedsyntax=docker/dockerfile:1
syntax=docker/dockerfile:1
RUN --mount=type=secret,id=pip_index_url
PIP_INDEX_URL=$(cat /run/secrets/pip_index_url)
uv sync --frozen --no-dev
PIP_INDEX_URL=$(cat /run/secrets/pip_index_url)
uv sync --frozen --no-dev
Pass the secret at build time:
```bash
docker build --secret id=pip_index_url,env=PIP_INDEX_URL .Secrets are available only during the instruction and never persist in the image history.
RUNRUN --mount=type=secret,id=pip_index_url
PIP_INDEX_URL=$(cat /run/secrets/pip_index_url)
uv sync --frozen --no-dev
PIP_INDEX_URL=$(cat /run/secrets/pip_index_url)
uv sync --frozen --no-dev
在构建时传递密钥:
```bash
docker build --secret id=pip_index_url,env=PIP_INDEX_URL .密钥仅在指令期间可用,永远不会保留在镜像历史中。
RUNCommon Labels
通用标签
Apply OCI-standard labels for image metadata:
dockerfile
LABEL org.opencontainers.image.title="my-fastapi-app"
LABEL org.opencontainers.image.description="FastAPI application"
LABEL org.opencontainers.image.version="1.0.0"
LABEL org.opencontainers.image.source="https://github.com/org/repo"应用OCI标准标签以添加镜像元数据:
dockerfile
LABEL org.opencontainers.image.title="my-fastapi-app"
LABEL org.opencontainers.image.description="FastAPI application"
LABEL org.opencontainers.image.version="1.0.0"
LABEL org.opencontainers.image.source="https://github.com/org/repo"Cross-References
交叉引用
- For uvicorn production configuration (workers, timeouts, logging), consult
the skill.
uvicorn - For uv dependency management (lockfiles, workspaces, scripts), consult the
skill.
uv
- 关于uvicorn的生产配置(工作进程、超时、日志),请参考技能文档。
uvicorn - 关于uv依赖管理(锁定文件、工作区、脚本),请参考技能文档。
uv