mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-29 03:02:55 +00:00
A dockerfile using `ubuntu` instead of `python` as base image currently silently fails to install. ```dockerfile FROM ubuntu RUN apt-get update && apt-get install -y curl --no-install-recommends RUN curl -LsSf https://astral.sh/uv/install.sh | sh RUN uv --version ``` ```console $ docker buildx build --progress plain --no-cache . [...] #6 [3/4] RUN curl -LsSf https://astral.sh/uv/install.sh | sh #6 0.144 curl: (77) error setting certificate file: /etc/ssl/certs/ca-certificates.crt #6 DONE 0.2s #7 [4/4] RUN uv --version #7 0.113 /bin/sh: 1: uv: not found #7 ERROR: process "/bin/sh -c uv --version" did not complete successfully: exit code: 127 ``` There's two underlying problems: Pipefail, and missing `ca-certificates`. In most shells, the source of a pipe erroring doesn't fail the entire command, so `curl -LsSf https://astral.sh/uv/install.sh | sh` passes even if the curl part fails. In bash, you can prefix the command with `set -o pipefail &&` to change this behavior. But in the `ubuntu` docker container, dash is the default shell, not bash. dash doesn't have a pipefail option (in the version in ubuntu), so the [best practice](https://docs.docker.com/build/building/best-practices/#using-pipes) is `RUN ["/bin/bash", "-c", "set -o pipefail && curl -LsSf https://astral.sh/uv/install.sh | sh"]`. That's not very readable, so i'm going for `RUN curl -LsSf https://astral.sh/uv/install.sh > /tmp/uv-installer.sh && sh /tmp/uv-installer.sh && rm /tmp/uv-installer.sh` instead. ```dockerfile FROM ubuntu RUN apt-get update && apt-get install -y curl --no-install-recommends RUN curl -LsSf https://astral.sh/uv/install.sh > /tmp/uv-installer.sh && sh /tmp/uv-installer.sh && rm /tmp/uv-installer.sh \ RUN uv --version ``` ```console $ docker buildx build --progress plain --no-cache . [...] #6 [3/3] RUN curl -LsSf https://astral.sh/uv/install.sh > /tmp/uv-installer.sh && sh /tmp/uv-installer.sh && rm /tmp/uv-installer.sh RUN uv --version #6 0.179 curl: (77) error setting certificate file: /etc/ssl/certs/ca-certificates.crt #6 ERROR: process "/bin/sh -c curl -LsSf https://astral.sh/uv/install.sh > /tmp/uv-installer.sh && sh /tmp/uv-installer.sh && rm /tmp/uv-installer.sh RUN uv --version" did not complete successfully: exit code: 77 ``` The source for this error is `ca-certificates` missing, which is a recommended package. We need to drop `--no-install-recommends` and the installation passes again.
117 lines
3.2 KiB
Markdown
117 lines
3.2 KiB
Markdown
# Using uv in Docker
|
|
|
|
## Running in Docker
|
|
|
|
A Docker image is published with a built version of uv available. To run a uv command in a
|
|
container:
|
|
|
|
```console
|
|
$ docker run ghcr.io/astral-sh/uv --help
|
|
```
|
|
|
|
## Installing uv
|
|
|
|
uv can be installed by copying from the official Docker image:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
FROM python:3.12-slim-bullseye
|
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
|
|
```
|
|
|
|
Or with the standalone installer:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
FROM python:3.12-slim-bullseye
|
|
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates
|
|
RUN curl -LsSf https://astral.sh/uv/install.sh > /tmp/uv-installer.sh && sh /tmp/uv-installer.sh && rm /tmp/uv-installer.sh
|
|
ENV PATH="/root/.cargo/bin/:$PATH"
|
|
```
|
|
|
|
Note this requires `curl` to be available.
|
|
|
|
In either case, it is best practice to pin to a specific uv version.
|
|
|
|
## Installing a package
|
|
|
|
Once uv is installed in an image, it can be used to install some packages.
|
|
|
|
The system Python environment is safe to use this context, since a container is already isolated.
|
|
The `--system` flag can be used to install in the system environment:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
RUN uv pip install --system ruff
|
|
```
|
|
|
|
To use the system Python environment by default, set the `UV_SYSTEM_PYTHON` variable:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
ENV UV_SYSTEM_PYTHON=1
|
|
```
|
|
|
|
Alternatively, a virtual environment can be created and activated:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
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"
|
|
```
|
|
|
|
When using a virtual environment, the `--system` flag should be omitted from uv invocations:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
RUN uv pip install ruff
|
|
```
|
|
|
|
## Installing requirements
|
|
|
|
To install requirements files, copy them into the container:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
COPY requirements.txt .
|
|
RUN uv pip install -r requirements.txt
|
|
```
|
|
|
|
## Installing a project
|
|
|
|
When installing a project alongside requirements, it is prudent to separate copying the requirements
|
|
from the rest of the source code. This allows the dependencies of the project (which do not change
|
|
often) to be cached separately from the project itself (which changes very frequently).
|
|
|
|
```dockerfile title="Dockerfile"
|
|
COPY pyproject.toml .
|
|
RUN uv pip install -r pyproject.toml
|
|
COPY . .
|
|
RUN uv pip install -e .
|
|
```
|
|
|
|
## Optimizations
|
|
|
|
### Using uv temporarily
|
|
|
|
If uv isn't needed in the final image, the binary can be mounted in each invocation:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
RUN --mount=from=uv,source=/uv,target=/bin/uv \
|
|
uv pip install --system ruff
|
|
```
|
|
|
|
### Caching
|
|
|
|
A [cache mount](https://docs.docker.com/build/guide/mounts/#add-a-cache-mount) can be used to
|
|
improve performance across builds:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
./uv pip install -r requirements.txt -->
|
|
```
|
|
|
|
Note the cache directory's location can be determined with the `uv cache dir` command.
|
|
Alternatively, the cache can be set to a constant location:
|
|
|
|
```dockerfile title="Dockerfile"
|
|
ENV UV_CACHE_DIR=/opt/uv-cache/
|
|
```
|
|
|
|
If not mounting the cache, image size can be reduced with `--no-cache` flag.
|