ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

uv 在 Docker 中的完整实践:官方镜像、项目构建、容器开发与镜像构建优化

uv 在 Docker 中的完整实践:官方镜像、项目构建、容器开发与镜像构建优化 uv 在 Docker 中的完整实践官方镜像、项目构建、容器开发与镜像构建优化【免费下载链接】uvAn extremely fast Python package and project manager, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/uv/uv本文以 uv 官方文档 Using uv in Docker 为核心系统讲解在 Docker 中安装和使用 uv 的完整方案从选择官方 distroless / 派生镜像到在镜像中安装项目、在容器内开发再到通过字节码编译、缓存挂载、中间层拆分、非可编辑安装等技巧优化构建时间最后覆盖 pip 接口用法与镜像来源验证。读完本文你可以直接复制文中的 Dockerfile 与 compose 配置构建出构建更快、体积更小、来源可信的 Python 应用镜像。官方镜像体系distroless 与派生镜像uv 提供两类官方 Docker 镜像托管于ghcr.io/astral-sh/uv仓库distroless 镜像只包含 uv 二进制不附带任何操作系统组件适合通过COPY --from把 uv 复制到你自己构建的镜像中派生镜像derived images基于流行的基础镜像Alpine、Debian、python 官方镜像等构建预装 uv适合直接在容器中使用 uv。例如用 Debian 基础镜像直接运行 uv$ docker run --rm -it ghcr.io/astral-sh/uv:debian uv --helpdistroless 镜像的“纯净”特性可以直接在本仓库根目录的 Dockerfile 中得到印证——它就是 uv 官方镜像的构建入口在 Ubuntu 快照环境中用 Rust 工具链交叉编译出uv与uvx最终FROM scratch仅把两个二进制拷入镜像见 DockerfileFROM scratch COPY --frombuild /uv /uvx / WORKDIR /io ENTRYPOINT [/uv]可用的镜像标签distroless 镜像提供以下标签ghcr.io/astral-sh/uv:latestghcr.io/astral-sh/uv:{major}.{minor}.{patch}例如ghcr.io/astral-sh/uv:0.12.9ghcr.io/astral-sh/uv:{major}.{minor}例如ghcr.io/astral-sh/uv:0.12该 minor 下的最新 patch 版本派生镜像按基础镜像分组以下为原文档列出的完整清单基础镜像可用标签alpine:3.23ghcr.io/astral-sh/uv:alpine、ghcr.io/astral-sh/uv:alpine3.23alpine:3.22ghcr.io/astral-sh/uv:alpine3.22debian:trixie-slimghcr.io/astral-sh/uv:debian-slim、ghcr.io/astral-sh/uv:trixie-slimbuildpack-deps:trixieghcr.io/astral-sh/uv:debian、ghcr.io/astral-sh/uv:trixiedhi.io/alpine-base:3.23ghcr.io/astral-sh/uv:alpine-dhi、ghcr.io/astral-sh/uv:alpine3.23-dhidhi.io/debian-base:trixie-debian13ghcr.io/astral-sh/uv:debian-dhi、ghcr.io/astral-sh/uv:trixie-dhidhi/python:3.xghcr.io/astral-sh/uv:python3.14-dhi、python3.13-dhi、python3.12-dhi、python3.11-dhi、python3.10-dhipython3.x-alpinepython3.15-rc-alpine/python3.15-rc-alpine3.23、python3.14-alpine/python3.14-alpine3.23、python3.13-alpine/python3.13-alpine3.23、python3.12-alpine/python3.12-alpine3.23、python3.11-alpine/python3.11-alpine3.23、python3.10-alpine/python3.10-alpine3.23、python3.9-alpine/python3.9-alpine3.22均为ghcr.io/astral-sh/uv:前缀python3.x-trixiepython3.15-rc-trixie、python3.14-trixie、python3.13-trixie、python3.12-trixie、python3.11-trixie、python3.10-trixie、python3.9-trixie均为ghcr.io/astral-sh/uv:前缀python3.x-slim-trixiepython3.15-rc-trixie-slim、python3.14-trixie-slim、python3.13-trixie-slim、python3.12-trixie-slim、python3.11-trixie-slim、python3.10-trixie-slim、python3.9-trixie-slim均为ghcr.io/astral-sh/uv:前缀与 distroless 镜像相同每个派生镜像也会发布带 uv 版本号的标签ghcr.io/astral-sh/uv:{major}.{minor}.{patch}-{base}和ghcr.io/astral-sh/uv:{major}.{minor}-{base}例如ghcr.io/astral-sh/uv:0.12.9-alpine。此外从0.8版本起每个派生镜像都会把UV_TOOL_BIN_DIR设置为/usr/local/bin使uv tool install对默认用户开箱即用。在你的镜像中安装 uv方式一直接使用预装 uv 的派生镜像方式二从官方 distroless 镜像复制二进制FROM python:3.12-slim-trixie COPY --fromghcr.io/astral-sh/uv:latest /uv /uvx /bin/注意这里的COPY --from恰好利用了 distroless 镜像只有/uv、/uvx两个文件的特点不会引入任何多余层内容。方式三通过官方安装脚本安装FROM python:3.12-slim-trixie # The installer requires curl (and certificates) to download the release archive RUN apt-get update apt-get install -y --no-install-recommends curl ca-certificates # Download the latest installer ADD https://astral.sh/uv/install.sh /uv-installer.sh # Run the installer then remove it RUN sh /uv-installer.sh rm /uv-installer.sh # Ensure the installed binary is on the PATH ENV PATH/root/.local/bin/:$PATH该方式要求镜像中可用curl。固定 uv 版本无论采用哪种方式固定到具体 uv 版本是最佳实践COPY --fromghcr.io/astral-sh/uv:0.12.9 /uv /uvx /bin/或者用固定版本的安装脚本ADD https://astral.sh/uv/0.12.9/install.sh /uv-installer.sh更进一步在要求可复现构建的环境中固定具体的 SHA256 digest 才是最佳实践——因为 tag 可能指向不同提交而 digest 不可变# e.g., using a hash from a previous release COPY --fromghcr.io/astral-sh/uvsha256:2381d6aa60c326b71fd40023f921a0a3b8f91b14d5db6b90402e65a635053709 /uv /uvx /bin/在镜像中安装项目如果项目由 uv 管理把它拷入镜像并同步即可# Copy the project into the image COPY . /app # Disable development dependencies ENV UV_NO_DEV1 # Sync the project into a new environment, asserting the lockfile is up to date WORKDIR /app RUN uv sync --locked这里有两个关键点ENV UV_NO_DEV1关闭开发依赖避免把dev依赖组测试、lint 工具等带进生产镜像--locked断言uv.lock是最新的锁文件缺失或与pyproject.toml不一致时构建直接失败从 CI 层面杜绝“镜像依赖漂移”。重要最佳实践是在仓库中添加.dockerignore文件并排除.venv。项目虚拟环境依赖本地平台绝不应该被打进镜像而应在镜像内从零创建。默认启动命令示例假设项目提供my_app可执行入口CMD [uv, run, my_app]最佳实践是配合下文“中间层”技巧把依赖安装与项目拷贝分离以缩短构建时间。使用环境激活虚拟环境或uv run项目安装完成后有两种使用方式把虚拟环境 bin 目录放到PATH最前面等效于激活环境ENV PATH/app/.venv/bin:$PATH所有需要环境的命令都走uv runRUN uv run some_script.py也可以设置UV_PROJECT_ENVIRONMENT把环境安装到系统 Python从而完全跳过“激活环境”这一步。使用已安装的工具uv tool install安装的工具可执行文件位于“tool bin 目录”。从源码看ToolDirArgs 的文档字符串明确给出了该目录的确定规则——按优先级依次查找环境变量$UV_TOOL_BIN_DIR、$XDG_BIN_HOME、$XDG_DATA_HOME/../bin最终回退到$HOME/.local/bin。因此在 Docker 中需要保证该目录在PATH上ENV PATH/root/.local/bin:$PATH RUN uv tool install cowsay$ docker run -it $(docker build -q .) /bin/bash -c cowsay -t hello _____ | hello | \ \ ^__^ (oo)\_______ (__)\ )\/\ ||----w | || ||工具 bin 目录的确切位置可在容器内运行uv tool dir --bin查看也可以把它固定到常量位置ENV UV_TOOL_BIN_DIR/opt/uv-bin/在容器内开发开发阶段把项目目录挂载进容器很有用改动即时反映到容器化服务无需重建镜像。但绝不能把项目虚拟环境.venv包含在挂载中——虚拟环境是平台相关的镜像里构建好的那份应该保留。用docker run挂载项目把项目工作目录绑定挂载到/app同时用匿名卷把.venv目录“保护”起来$ docker run --rm --volume .:/app --volume /app/.venv [...]--rm保证容器退出时匿名卷一并清理。用docker compose配置watch使用 Compose 时有更精细的工具watch选项的粒度高于 bind mount并支持在文件变化时触发容器内服务的更新需要 Compose 2.22.0随 Docker Desktop 4.24 提供。在 compose 文件中配置watch同步项目目录但排除.venv并在pyproject.toml变化时重建镜像services: example: build: . # ... develop: # Create a watch configuration to update the app # watch: # Sync the working directory with the /app directory in the container - action: sync path: . target: /app # Exclude the project virtual environment ignore: - .venv/ # Rebuild the image on changes to the pyproject.toml - action: rebuild path: ./pyproject.toml之后运行docker compose watch即可在开发配置下运行容器。构建优化编译字节码将 Python 源码编译为字节码通常有利于生产镜像——运行时启动更快代价是安装时间与镜像体积增加。启用方式RUN uv python install --compile-bytecode RUN uv sync --compile-bytecode或者设置UV_COMPILE_BYTECODE环境变量让 Dockerfile 中所有 uv 命令都编译字节码对应 CLI 参数与环境变量的绑定见 crates/uv-cli/src/lib.rs 中env EnvVars::UV_COMPILE_BYTECODE的定义ENV UV_COMPILE_BYTECODE1需要注意uv 只会在uv python install时为受管managedPython编译标准库不受管 Python 的标准库是否预编译由发行方决定例如官方python镜像就没有预编译标准库。缓存挂载用 BuildKit 缓存挂载 可以在多次构建之间复用下载缓存ENV UV_LINK_MODEcopy RUN --mounttypecache,target/root/.cache/uv \ uv sync设置UV_LINK_MODE该变量在 crates/uv-cli/src/lib.rs 中以env EnvVars::UV_LINK_MODE绑定到link_mode参数为copy可消除“缓存目录与同步目标位于不同文件系统、无法 link 文件”的警告。如果不挂载缓存则可用--no-cache标志或UV_NO_CACHE变量减小镜像体积。受管 Python 的下载默认不会在安装前缓存可以设置UV_PYTHON_CACHE_DIR配合缓存挂载ENV UV_PYTHON_CACHE_DIR/root/.cache/uv/python RUN --mounttypecache,target/root/.cache/uv \ uv python install缓存目录位置可用容器内的uv cache dir命令查看也可以固定为常量ENV UV_CACHE_DIR/opt/uv-cache/中间层把依赖安装拆成独立层如果项目由 uv 管理可以把传递依赖的安装移入独立层显著改善构建时间。uv sync --no-install-project会安装项目的全部依赖但不安装项目本身——项目代码经常变、依赖相对稳定这一拆分收益很大。这一点在源码中有直接佐证SyncArgs 中--no-install-project的帮助文本明确写道该选项“在构建 Docker 镜像等场景下特别有用把项目与其依赖分开安装可以实现最优的层缓存”同组还有--no-install-workspace排除全部工作区成员但保留依赖、--no-install-local跳过所有本地路径包只装远程依赖帮助文本同样点明其 Docker 层缓存用途。# Install uv FROM python:3.12-slim COPY --fromghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # Change the working directory to the app directory WORKDIR /app # Install dependencies RUN --mounttypecache,target/root/.cache/uv \ --mounttypebind,sourceuv.lock,targetuv.lock \ --mounttypebind,sourcepyproject.toml,targetpyproject.toml \ uv sync --locked --no-install-project # Copy the project into the image COPY . /app # Sync the project RUN --mounttypecache,target/root/.cache/uv \ uv sync --locked注意pyproject.toml用于确定项目根与项目名称因此首次依赖层只需要绑定挂载uv.lock与pyproject.toml两个文件项目内容直到最后一次uv sync才被拷入镜像。若只想在同步中额外排除某些特定包使用--no-install-package name。工作区workspace场景如果使用 workspace需要两处调整首次同步用--frozen代替--locked使用--no-install-workspace排除项目以及所有工作区成员。# Install uv FROM python:3.12-slim COPY --fromghcr.io/astral-sh/uv:latest /uv /uvx /bin/ WORKDIR /app RUN --mounttypecache,target/root/.cache/uv \ --mounttypebind,sourceuv.lock,targetuv.lock \ --mounttypebind,sourcepyproject.toml,targetpyproject.toml \ uv sync --frozen --no-install-workspace COPY . /app RUN --mounttypecache,target/root/.cache/uv \ uv sync --locked原因没有各工作区成员的pyproject.tomluv 无法断言uv.lock是最新的所以首次同步必须用--frozen直接使用锁文件内容、跳过“锁文件是否为最新”的校验而成员全部拷贝后的第二次同步仍可安全使用--locked完成完整校验。这两个模式的区别可参见 SyncArgs 中locked与frozen的参数定义--locked在锁文件缺失或过期时报错--frozen则直接以锁文件为唯一事实来源。非可编辑安装多阶段构建只携带虚拟环境默认情况下uv 以可编辑editable模式安装项目与工作区成员源码改动即时反映到环境中。uv sync与uv run都接受--no-editable标志指示 uv 以非可编辑模式安装项目、彻底解除对源码路径的依赖参数定义见 crates/uv-cli/src/lib.rs也可通过UV_NO_EDITABLE环境变量设置。在多阶段 Docker 镜像中可以用--no-editable在 builder 阶段把项目装进虚拟环境然后**只拷贝虚拟环境不拷源码**到最终镜像# Install uv FROM python:3.12-slim AS builder COPY --fromghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # Use the system Python across both stages ENV UV_PYTHON_DOWNLOADS0 # Change the working directory to the app directory WORKDIR /app # Install dependencies RUN --mounttypecache,target/root/.cache/uv \ --mounttypebind,sourceuv.lock,targetuv.lock \ --mounttypebind,sourcepyproject.toml,targetpyproject.toml \ uv sync --locked --no-install-project --no-editable # Copy the project into the intermediate image COPY . /app # Sync the project RUN --mounttypecache,target/root/.cache/uv \ uv sync --locked --no-editable FROM python:3.12-slim # Copy the environment, but not the source code COPY --frombuilder /app/.venv /app/.venv # Run the application CMD [/app/.venv/bin/hello]UV_PYTHON_DOWNLOADS0保证两个阶段使用同一个系统 Python使 builder 阶段构建的.venv可以被最终镜像安全复用这也是前提两阶段基础镜像的 Python 版本必须一致。临时使用 uv如果最终镜像根本不需要 uv可以在每次调用时挂载二进制而不把它装进任何层RUN --mountfromghcr.io/astral-sh/uv,source/uv,target/bin/uv \ uv sync使用 pip 接口安装包容器本身就是隔离环境系统 Python 环境在此语境下是安全的用--system安装到系统环境RUN uv pip install --system ruff或设置变量让系统环境成为默认ENV UV_SYSTEM_PYTHON1也可以创建并激活虚拟环境RUN uv venv /opt/venv # Use the virtual environment automatically ENV VIRTUAL_ENV/opt/venv # Place entry points in the environment at the front of the path ENV PATH/opt/venv/bin:$PATH使用虚拟环境时uv 调用应省略--systemRUN uv pip install ruff安装 requirements 文件把 requirements 拷入容器即可COPY requirements.txt . RUN uv pip install -r requirements.txt安装项目本体把“拷贝依赖声明”和“拷贝其余源码”分开是最佳实践这样项目的依赖很少变与项目本身经常变可以被分别缓存COPY pyproject.toml . RUN uv pip install -r pyproject.toml COPY . . RUN uv pip install -e .验证镜像来源Provenanceuv 的 Docker 镜像在构建过程中被签名产生来源证明attestation可用来验证镜像确实由官方渠道产出。例如用 GitHub CLI 的gh验证$ gh attestation verify --owner astral-sh oci://ghcr.io/astral-sh/uv:latest Loaded digest sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx for oci://ghcr.io/astral-sh/uv:latest Loaded 1 attestation from GitHub API The following policy criteria will be enforced: - OIDC Issuer must match:................... https://token.actions.githubusercontent.com - Source Repository Owner URI must match:... https://github.com/astral-sh - Predicate type must match:................ https://slsa.dev/provenance/v1 - Subject Alternative Name must match regex: (?i)^https://github.com/astral-sh/ ✓ Verification succeeded! sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx was attested by: REPO PREDICATE_TYPE WORKFLOW astral-sh/uv https://slsa.dev/provenance/v1 .github/workflows/build-docker.ymlrefs/heads/main这说明该镜像由 uv 官方 GitHub 发布工作流构建、且此后未被篡改。GitHub 证明基于 sigstore 基础设施因此也可以用cosign命令把证明 blob 与uv的多平台 manifest 做校验$ REPOastral-sh/uv $ gh attestation download --repo $REPO oci://ghcr.io/${REPO}:latest Wrote attestations to file sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jsonl. Any previous content has been overwritten The trusted metadata is now available at sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jsonl $ docker buildx imagetools inspect ghcr.io/${REPO}:latest --format {{json .Manifest}} manifest.json $ cosign verify-blob-attestation \ --new-bundle-format \ --bundle $(jq -r .digest manifest.json).jsonl \ --certificate-oidc-issuerhttps://token.actions.githubusercontent.com \ --certificate-identity-regexp^https://github\.com/${REPO}/.* \ (jq -j .|del(.digest,.size) manifest.json) Verified OK提示示例使用latest但最佳实践是对具体版本标签如ghcr.io/astral-sh/uv:0.12.9或具体镜像 digest如ghcr.io/astral-sh/uv:0.5.27sha256:5adf09a5a526f380237408032a9308000d14d5947eafa687ad6c6a2476787b4f验证证明这与上文“固定版本 / 固定 digest”的安装建议一脉相承。小结在 Docker 中使用 uv 的完整链路可以概括为引入优先COPY --from官方 distroless 镜像固定版本或 digest或安装脚本安装项目UV_NO_DEV1uv sync --locked.dockerignore排除.venv开发bind mount 匿名卷保护.venv或 Composewatchsync 排除.venv、pyproject.toml变化触发 rebuild优化--compile-bytecode提速启动、缓存挂载配合UV_LINK_MODEcopy提速下载、--no-install-project/--no-install-workspace拆中间层、--no-editable支持“只拷环境不拷源码”的多阶段构建信任用gh attestation verify或cosign verify-blob-attestation对具体标签 / digest 验证镜像来源。配合本仓库 Dockerfile官方镜像自身的构建过程与 crates/uv-cli/src/lib.rs 中uv sync相关参数定义可以把上述每条实践落到可复现、可审计的具体命令上。【免费下载链接】uvAn extremely fast Python package and project manager, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/uv/uv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表