Home > other >  Setting USER in Dockerfile prevents saving file fields (eg. ImageField) in Django
Setting USER in Dockerfile prevents saving file fields (eg. ImageField) in Django

Time:05-21

I am trying to containerize Django with Dockerfile and docker-compose.yml as defined below. I built the Dockerfile as (fiifidev/postgres:test) for the compose file. Everything works fine. However anytime I try to save a model with a file field (eg. ImageField or FileField), I get Permission Error PermissionError: [Errno 13] Permission denied docker.

I suspect I am not adding the appropriate permission of user creation (useradd) in the Dockerfile (not sure). But when I remove the USER everything works fine.

How can I fix this any help will be much appreciated.

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

CodePudding user response:

From Dockerfile:

WORKDIR /home/appuser/src
USER appuser

# Install application into container
COPY --chown=appuser:appuser . .

Here you are creating a src directory and copying your code into it. This is baked into the resulting image.

From docker-compose.yml:

    volumes:
      - .:/home/appuser/src

Here you are mounting the current directory on your host on top of the the src directory. A mount will take precedence over the image's idea of what a directory contains, so this effectively means your COPY and chown have no effect. (Those files are still there in your image, but the mount hides them; they are not available.)

The behavior as far as permissions here will vary by platform. On Windows, I don't know what would happen. Using Docker Desktop on Mac it would "just work", because Docker Desktop more or less ignores the permissions in this case and makes everything happy.

On Linux, however, the file ownership inside the container and outside the container must match for you to be able to write to it. What's probably happening is that the files in your mounted directory are owned by a different uid (yours) than the 'appuser' in the container has. Therefore, you get permission errors because you don't have permission to write to the files/directory.

There are two solutions you could try:

  1. Chown the files in the host directory (outside the container) to have the same uid that 'appuser' has inside the container.
  2. Or you could specify the uid of 'appuser' when creating it (during the image build). In that case, specify 'appuser' has the same UID as your user on the Linux host. It wouldn't matter if the Linux user has a different name; if the uid number is the same, then you will have permissions.
  • Related