Skip to content

Add --root flag for uv pip install#18774

Open
fdfz wants to merge 1 commit intoastral-sh:mainfrom
fdfz:pip-root
Open

Add --root flag for uv pip install#18774
fdfz wants to merge 1 commit intoastral-sh:mainfrom
fdfz:pip-root

Conversation

@fdfz
Copy link
Copy Markdown

@fdfz fdfz commented Mar 31, 2026

Purpose of the change:

By using the --root flag, you can install packages into a directory separate from your host filesystem—a technique particularly useful for constructing minimal containers.

This approach is perfect for multi-stage Docker builds, as it allows you to generate a clean, isolated set of dependencies to be copied into a final image that doesn't necessarily have the tools or environment to run the installer itself (because e.g. pip is not installed).

Example with pip:

FROM python:alpine AS builder
# Possibly install prerequisites, gcc, etc, that aren't needed in runtime
COPY requirements.txt ./
RUN pip install -r requirements.txt --root /root-dir
# Do other installs / builds...

FROM python:alpine
COPY --from=builder /root-dir /
# Other stuff as needed

Detailed changes:

This PR adds the --root option to uv pip install, uv pip uninstall, uv pip sync, uv pip freeze, uv pip show, and uv pip list.

The usage and behavior are fully consistent with pip.

Test Plan

Added comprehensive test cases.

@fdfz fdfz force-pushed the pip-root branch 11 times, most recently from 083e276 to 5fe2774 Compare March 31, 2026 10:14
@konstin
Copy link
Copy Markdown
Member

konstin commented Mar 31, 2026

Can you describe why the current set of options isn't sufficient, and why you can't use a venv?

@fdfz
Copy link
Copy Markdown
Author

fdfz commented Mar 31, 2026

Can you describe why the current set of options isn't sufficient, and why you can't use a venv?

@konstin Currently, uv's existing options do not offer a straightforward way to generate a 'clean' container image (free of redundant files). Relying on virtual environments (venvs) for this specific use case presents two significant drawbacks:

  1. Container Bloat: For single-purpose containers, installing packages system-wide is standard practice and logically sound. Using a venv adds unnecessary overhead and increases the final image size without providing any benefit in this context.
  2. Logical Complexity and Fragmentation: Venvs introduce unnecessary complexity into the build logic. If a container user installs additional Python packages at runtime (e.g., via an entrypoint), those are typically installed system-wide. However, the packages installed during the build phase would reside inside the venv. Unless one explicitly enables system-site-package inheritance, this creates a fragmented environment.

In contrast, the pip install --root workflow allows us to generate exactly the required files in a temporary directory during a multi-stage build. We can then simply use COPY --from=builder /root-dir / to produce a minimal, production-ready container while avoiding the issues mentioned above.

uv positions itself as a drop-in replacement for pip. If uv cannot support a core pip workflow for constructing minimal containers, it leaves a significant functional gap. As far as I can see, many Python packages’ containers are built using pip install --root.

Furthermore, there is clearly established community demand for this feature, as evidenced by the discussions in:

@konstin
Copy link
Copy Markdown
Member

konstin commented Mar 31, 2026

Please do not use LLMs write responses (https://github.com/astral-sh/.github/blob/main/AI_POLICY.md), instead describe your specific problem in your own words.

@fdfz
Copy link
Copy Markdown
Author

fdfz commented Mar 31, 2026

Please do not use LLMs write responses (https://github.com/astral-sh/.github/blob/main/AI_POLICY.md), instead describe your specific problem in your own words.

@konstin My English isn’t that good—I’m just using AI for translation, but the ideas I’m expressing are my own.

In simple terms, uv currently cannot produce the simplest and smallest possible container image.

  1. When building a Python package container with uv, dependencies are installed into a virtual environment (venv) during the build stage, while packages installed later by container users (e.g., plugins) go into the system-wide environment. By default, venv and system-wide site-packages are isolated from each other.
  2. Conceptually, a container is meant to be single-purpose, so introducing a venv adds unnecessary complexity.
  3. The structure of a venv also increases the container size.
  4. Since uv claims to be a drop-in replacement for pip, it should be able to produce the same minimal, smallest-size container structure as pip install --root.

The issue #13129 with a similar request clearly explains the necessity of the --root option.

@fdfz
Copy link
Copy Markdown
Author

fdfz commented Mar 31, 2026

For example, as I mentioned in the first point above, the packages installed during the container build and those installed by the user in the entrypoint are separated by default, which leads to this issue:

Although this can be resolved by configuring a virtual environment, it introduces additional complexity.

The simplest, most straightforward, and least error-prone approach—and also the most common practice—is to install all packages into the system-wide site-packages within the container.

@konstin
Copy link
Copy Markdown
Member

konstin commented Mar 31, 2026

A venv is barely any overhead, and I'm not sure if --root is the correct alternative. Following #13129, I don't think we want to implement this feature at this point.

@fdfz
Copy link
Copy Markdown
Author

fdfz commented Mar 31, 2026

A venv is barely any overhead, and I'm not sure if --root is the correct alternative. Following #13129, I don't think we want to implement this feature at this point.

However, #13129 was rejected because @zanieb believed that the --root option would be difficult to implement and maintain. But if you take a look at my code, you'll see it is modeled entirely after uv pip install --prefix and uv pip install --target. The implementation is concise and clear, so it won't add any significant maintenance complexity.

Furthermore, the original context for implementing uv pip install --prefix was for installing Python packages within containers. In reality, uv pip install --root is a much better fit for this use case; with --prefix, you have to know the specific site-packages path (which varies across platforms), whereas with the --root option, you don't need to worry about that at all.

If you believe merging this PR would increase the complexity of the codebase, then you should also consider removing the uv pip install --prefix option (Because uv pip install --root is a superior alternative to uv pip install --prefix in every way.).

@fdfz
Copy link
Copy Markdown
Author

fdfz commented Mar 31, 2026

A venv is barely any overhead, and I'm not sure if --root is the correct alternative. Following #13129, I don't think we want to implement this feature at this point.

The uv documentation states that uv pip is for 'Managing Python packages with a pip-compatible interface.'

@konstin Since pip install --root uses the name 'root', and uv pip claims to be a 'pip-compatible interface', it stands to reason that it should use the same 'root' naming and implement the exact same functionality as pip install --root.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants