Установка 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.

Есть два решения, которые вы могли бы попробовать:

  1. Переименуйте файлы в директории хоста (вне контейнера), чтобы они имели тот же uid, что и 'appuser' внутри контейнера.
  2. Или вы можете указать uid 'appuser' при его создании (во время сборки образа). В этом случае укажите, что 'appuser' имеет тот же UID, что и ваш пользователь на Linux-хосте. Не имеет значения, если пользователь Linux имеет другое имя; если номер uid одинаковый, то у вас будут разрешения.
Вернуться на верх