I have a Docker dev setup that works fine on Mac and Windows with Hyper-V but not on Windows with WSL2. When Python attempts to execute a makedirs
command, we get a PermissionError: [Errno 13] Permission denied
error. For example, when attempting to make /code/static
, we get:
PermissionError: [Errno 13] Permission denied: '/code/static'
Similarly for Django's makemigrations
command, which attempts to make a migrations directory at /code/website/migrations
we get:
PermissionError: [Errno 13] Permission denied: '/code/website/migrations'
But our Dockerfile clearly gives the apache
user permission to the /code/
folder. Here's the full Dockerfile:
# All Dockerfiles must start with a 'FROM' instruction, which specifies a base image
# See: https://docs.docker.com/engine/reference/builder/#format
# Note, some online sources say that you should put FROM django here (e.g., https://runnable.com/docker/python/dockerize-your-django-application)
# but, in fact, you should NOT do this according to the official docs (as this approach has been deprecated).
# See: https://hub.docker.com/_/django/
FROM python:3.8
# Sometimes we get warnings about old pip, so take care of that here
RUN pip install --upgrade pip
# See: https://www.quora.com/How-does-one-install-pip-in-a-Docker-container-using-a-Dockerfile
RUN apt-get update && apt-get --assume-yes install imagemagick ghostscript sqlite3
# The ENV instruction sets the environment variable <key> to the <value> in ENV <key> <value>.
# See: https://docs.docker.com/engine/reference/builder/#environment-replacement
# In this case, we are setting the stdout/stderr streams in Python to be unbuffered
ENV PYTHONUNBUFFERED 1
#Create a system user which we'll use later.
#We're using the 'apache' user since that's what we're trying to map
#outside the container -- it could be called anything, but apache is convenient
RUN useradd -u 48 apache
RUN groupmod -g 48 apache
# The RUN instruction will execute any commands in a new layer on top of the current image and commit the results.
# The resulting committed image will be used for the next step in the Dockerfile.
# See: https://docs.docker.com/engine/reference/builder/#run
RUN mkdir /code
# The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions
# that follow it in the Dockerfile. If the WORKDIR doesn’t exist, it will be created even if it’s not used
# in any subsequent Dockerfile instruction.
# See: https://docs.docker.com/engine/reference/builder/#workdir
WORKDIR /code
#COPY the requirements.txt into the docker container
# As an fyi: Layering RUN instructions and generating commits conforms to the core concepts
# of Docker where commits are cheap and containers can be created from any point in an image’s history, much like source control.
# See: https://docs.docker.com/engine/reference/builder/#run
COPY requirements.txt /code/
RUN pip3.8 install -r requirements.txt
## TEMP related to: https://github.com/jonfroehlich/makeabilitylabwebsite/issues/866
#RUN pip install django-ckeditor
# Our local user needs write access to a website and static files
RUN chown -R apache /code/
# Despite the above, still getting permission errors on WSL2
# -- PermissionError: [Errno 13] Permission denied: '/code/static'
# -- PermissionError: [Errno 13] Permission denied: '/code/website/migrations'
# RUN chown apache:apache -R /code/
COPY . /code/
#Run the process as our local user:
USER apache
COPY docker-entrypoint.sh docker-entrypoint.sh
CMD ["/code/docker-entrypoint.sh"]
You can see the full repo here in case it's useful, including our Dockerfile, our docker-compose.yml, and our docker-entrypoint.sh script.
Update
Based on @LiquidDeath's suggestion, I added the following to my Dockerfile right after the RUN mkdir /code
statement.
RUN mkdir -p /code/static
RUN mkdir -p /code/website/migrations
RUN echo $(ls -al)
RUN echo $(ls -al /code)
RUN chmod -R 777 /code/static/
RUN chmod -R 777 /code/website/migrations/
And I checked that these dirs were indeed created by running the docker build command with --progress=plain
and --no-cache
flags.
However, I am still getting the same PermissionError: [Errno 13] Permission denied
problem once I actually run docker-compose up
| ****************** STEP 1: docker-entrypoint.sh ************************
| 1. Collecting static files
| ******************************************
| Traceback (most recent call last):
| File "manage.py", line 10, in <module>
| execute_from_command_line(sys.argv)
| File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
| utility.execute()
| File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 375, in execute
| self.fetch_command(subcommand).run_from_argv(self.argv)
| File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 316, in run_from_argv
| self.execute(*args, **cmd_options)
| File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 353, in execute
| output = self.handle(*args, **options)
| File "/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 188, in handle
| collected = self.collect()
| File "/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 114, in collect
| handler(path, prefixed_path, storage)
| File "/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 353, in copy_file
| self.storage.save(prefixed_path, source_file)
| File "/usr/local/lib/python3.8/site-packages/django/core/files/storage.py", line 49, in save
| return self._save(name, content)
| File "/usr/local/lib/python3.8/site-packages/django/core/files/storage.py", line 236, in _save
| os.makedirs(directory)
| File "/usr/local/lib/python3.8/os.py", line 213, in makedirs
| makedirs(head, exist_ok=exist_ok)
| File "/usr/local/lib/python3.8/os.py", line 213, in makedirs
| makedirs(head, exist_ok=exist_ok)
| File "/usr/local/lib/python3.8/os.py", line 223, in makedirs
| mkdir(name, mode)
| PermissionError: [Errno 13] Permission denied: '/code/static'
CodePudding user response:
That might be because in your Mac and Windows with Hyper-V, the containers are run with root privileges. But WSL2 is not allowing you to run as root. As a solution you can give necessary permissions(write/execute) to the directories/files.
In you docker file add the below lines
RUN chown -R apache /code/
COPY . /code/
RUN chmod -R 777 /code/static/
RUN chmod -R 777 /code/website/migrations/
777 gives full permission to owner, user and others, change this permission as per your requirement (refer to permissions in linux)