I have a Django app build by uv running inside Docker. I mount the local filesystem as a volume in the container using Docker Compose so that edits to the source code locally trigger reloading of the app in the container. It almost works.
The issue is that the .venv directory built by uv is owned by the root user of the Docker container. This means that I cannot edit those files from my local filesystem without root access.
I have gotten around this with pip/pipenv/poetry/pdm in the past by installing the venv as a non-root user who has the same uid and guid as my local user (those values are passed into Docker via a .env file). But I can't work out how to do that for uv.
Dockerfile:
FROM python:3.12-slim-trixie
# create non-root user
RUN addgroup --system appuser && adduser --system --group --home /home/appuser appuser
# set work directory
WORKDIR /app
# environment variables
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
UV_LINK_MODE=copy \
UV_PYTHON_DOWNLOADS=never \
UV_PROJECT_ENVIRONMENT=$APP_HOME/.venv
# install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# install system dependencies
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
build-essential netcat-traditional \
python-is-python3 python3-gdal python3-psycopg2
# switch to app user [THIS MAKES THE NEXT COMMAND FAIL]
# USER appuser
# synchronise project dependencies
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=/root/.cache \
uv sync --all-groups --frozen --no-install-project
# run entrypoint script
COPY ./entrypoint.sh .
RUN chmod +x entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]
docker-compose.yml:
services:
server:
build:
context: .
command: uv run manage.py runserver 0.0.0.0:8000
tty: true
environment:
DJANGO_SETTINGS_MODULE: config.settings
volumes:
- ./:/app/
ports:
- "8000:8000"
env_file:
- .env
entrypoint.sh:
#!/bin/sh
set -euo pipefail
cd /app
# ensure "app" user in the container has same ids as local user outside the container
if [ ! -z ${RUN_AS_UID} ]; then usermod --uid $RUN_AS_UID appuser; fi
if [ ! -z ${RUN_AS_GID} ]; then groupmod --gid $RUN_AS_GID apuser; fi
# setup django
uv run ./manage.py migrate
uv run ./manage.py collectstatic --no-input --link
# run whatever command was passed to the container (from docker-compose)
exec "$@"
.env:
RUN_AS_UID=1001
RUN_AS_GID=1001
RUN sudo -u appuser uv sync?error: failed to create directory/app/.venv: Permission denied (os error 13).cdsomeplace writable when creating the python virt environment. Orchown -R appuser /app