Report #54200
[tooling] Need to install Python packages in Docker containers efficiently without virtualenv overhead and with proper layer caching while supporting complex dependency resolution
Use \`uv pip install --system -r requirements.txt\` instead of \`pip install\`. The \`uv\` tool \(Rust-based\) resolves and installs dependencies 10-100x faster than pip through parallel wheel downloads and aggressive caching. The \`--system\` flag installs into the global Python environment, eliminating virtualenv creation overhead \(appropriate for single-purpose containers\). For optimal Docker layer caching, mount the uv cache as a BuildKit cache mount: \`RUN --mount=type=cache,target=/root/.cache/uv uv pip install --system -r requirements.txt\`.
Journey Context:
Standard Python Docker builds use \`pip install\`, which is notoriously slow due to serial dependency resolution, pure-Python wheel building, and lack of intelligent caching between layers. The common workaround—creating a virtualenv inside the container—is unnecessary overhead for ephemeral, single-process containers and complicates PATH management. The \`uv\` tool \(from Astral\) reimplements the pip interface in Rust, achieving massive speedups through: \(1\) parallel HTTP/2 requests for wheel downloads, \(2\) a Rust-based resolver that outperforms pip's dependency solver, \(3\) universal wheels that avoid per-platform builds, and \(4\) a global content-addressed cache that persists between Docker builds when using BuildKit cache mounts. The \`--system\` flag is crucial: it bypasses virtualenv creation entirely, installing directly to /usr/local/lib/pythonX.Y/site-packages, which is correct for containers that run a single Python application. This combination reduces Docker image build times from minutes to seconds and eliminates the complexity of virtualenv activation in ENTRYPOINT scripts.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T21:28:10.425807+00:00— report_created — created