Установка USER в Dockerfile не позволяет сохранить поля файла (например, ImageField) в Django
Я пытаюсь контейнеризировать Django с помощью Dockerfile и docker-compose.yml, как определено ниже. Я создал Dockerfile как (fiifidev/postgres:test) для файла compose. Все работает нормально. Однако при попытке сохранить модель с полем файла (например, ImageField или FileField) я получаю Permission Error PermissionError: [Errno 13] Permission denied docker.
Я подозреваю, что не добавляю соответствующее разрешение на создание пользователя (useradd) в Dockerfile (не уверен). Но когда я удаляю USER, все работает нормально.
Как я могу это исправить, любая помощь будет очень признательна.
FROM python:3.10-slim-bullseye as base
# Setup env
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONFAULTHANDLER 1
FROM base AS python-deps
# Install pipenv and compilation dependencies
RUN pip install pipenv
RUN apt-get update && apt-get install -y --no-install-recommends gcc
# Install python dependencies in /.venv
COPY Pipfile .
COPY Pipfile.lock .
RUN PIPENV_VENV_IN_PROJECT=1 pipenv install --deploy
FROM base AS runtime
# Copy virtual env from python-deps stage
COPY --from=python-deps /.venv /.venv
ENV PATH="/.venv/bin:$PATH"
# Create and switch to a new user
RUN useradd --create-home appuser
WORKDIR /home/appuser/src
USER appuser
# Install application into container
COPY --chown=appuser:appuser . .
version: "3.9"
services:
web:
image: fiifidev/postgres:test
command: sh -c "python manage.py makemigrations &&
python manage.py migrate &&
python manage.py initiate_admin &&
python manage.py runserver 0.0.0.0:8000"
volumes:
- .:/home/appuser/src
networks:
postgres-network:
env_file:
- .env
ports:
- ${APP_PORT}:8000
restart: "on-failure"
networks:
postgres-network:
external: true
Из Dockerfile:
WORKDIR /home/appuser/src
USER appuser
# Install application into container
COPY --chown=appuser:appuser . .
Здесь вы создаете каталог src и копируете в него свой код. Это запекается в полученном изображении.
Из docker-compose.yml:
volumes:
- .:/home/appuser/src
Здесь вы монтируете текущий каталог на вашем хосте поверх каталога src. Монтирование имеет приоритет над представлением образа о том, что содержит каталог, так что это означает, что ваши COPY и chown не имеют никакого эффекта. (Эти файлы все еще находятся в вашем образе, но монтирование скрывает их; они недоступны.)
Поведение в отношении разрешений здесь будет зависеть от платформы. На Windows я не знаю, что произойдет. При использовании Docker Desktop на Mac это будет "просто работать", потому что Docker Desktop более или менее игнорирует разрешения в этом случае и делает все счастливым.
В Linux, однако, чтобы вы могли писать в контейнер, права собственности на файлы внутри контейнера и вне его должны совпадать. Вероятно, дело в том, что файлы в смонтированном каталоге принадлежат другому uid (вашему), чем у 'appuser' в контейнере. Поэтому вы получаете ошибки разрешения, поскольку у вас нет разрешения на запись в каталог files/directory.
Есть два решения, которые вы могли бы попробовать:
- Переименуйте файлы в директории хоста (вне контейнера), чтобы они имели тот же uid, что и 'appuser' внутри контейнера.
- Или вы можете указать uid 'appuser' при его создании (во время сборки образа). В этом случае укажите, что 'appuser' имеет тот же UID, что и ваш пользователь на Linux-хосте. Не имеет значения, если пользователь Linux имеет другое имя; если номер uid одинаковый, то у вас будут разрешения.