title: PermissionError: [Errno 13] Permission denied on Windows with WSL2 and Docker
body: <p>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 <code>makedirs</code> command, we get a <code>PermissionError: [Errno 13] Permission denied</code> error. For example, when attempting to make <code>/code/static</code>, we get:</p>
  <pre><code>PermissionError: [Errno 13] Permission denied: '/code/static'
  </code></pre>
  <p>Similarly for Django's <code>makemigrations</code> command, which attempts to make a migrations directory at <code>/code/website/migrations</code> we get:</p>
  <pre><code>PermissionError: [Errno 13] Permission denied: '/code/website/migrations'
  </code></pre>
  <p>But our <a href="https://github.com/makeabilitylab/makeabilitylabwebsite/blob/master/Dockerfile" rel="nofollow noreferrer">Dockerfile</a> clearly gives the <code>apache</code> user permission to the <code>/code/</code> folder. Here's the full Dockerfile:</p>
  <pre><code># 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 &amp;&amp; apt-get --assume-yes install imagemagick ghostscript sqlite3
  
  # The ENV instruction sets the environment variable &lt;key&gt; to the &lt;value&gt; in ENV &lt;key&gt; &lt;value&gt;. 
  # 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 [&quot;/code/docker-entrypoint.sh&quot;] 
  </code></pre>
  <p>You can see the <a href="https://github.com/makeabilitylab/makeabilitylabwebsite" rel="nofollow noreferrer">full repo here</a> in case it's useful, including our Dockerfile, our docker-compose.yml, and our docker-entrypoint.sh script.</p>
  <h1>Update</h1>
  <p>Based on @LiquidDeath's suggestion, I added the following to my Dockerfile right after the <code>RUN mkdir /code</code> statement.</p>
  <pre><code>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/
  </code></pre>
  <p>And I checked that these dirs were indeed created by running the docker build command with <code>--progress=plain</code> and <code>--no-cache</code> flags.</p>
  <p>However, I am still getting the same <code>PermissionError: [Errno 13] Permission denied</code> problem once I actually run <code>docker-compose up</code></p>
  <pre><code> | ****************** STEP 1: docker-entrypoint.sh ************************
   | 1. Collecting static files
   | ******************************************
   | Traceback (most recent call last):
   |   File &quot;manage.py&quot;, line 10, in &lt;module&gt;
   |     execute_from_command_line(sys.argv)
   |   File &quot;/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py&quot;, line 381, in execute_from_command_line
   |     utility.execute()
   |   File &quot;/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py&quot;, line 375, in execute
   |     self.fetch_command(subcommand).run_from_argv(self.argv)
   |   File &quot;/usr/local/lib/python3.8/site-packages/django/core/management/base.py&quot;, line 316, in run_from_argv
   |     self.execute(*args, **cmd_options)
   |   File &quot;/usr/local/lib/python3.8/site-packages/django/core/management/base.py&quot;, line 353, in execute
   |     output = self.handle(*args, **options)
   |   File &quot;/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py&quot;, line 188, in handle
   |     collected = self.collect()
   |   File &quot;/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py&quot;, line 114, in collect
   |     handler(path, prefixed_path, storage)
   |   File &quot;/usr/local/lib/python3.8/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py&quot;, line 353, in copy_file
   |     self.storage.save(prefixed_path, source_file)
   |   File &quot;/usr/local/lib/python3.8/site-packages/django/core/files/storage.py&quot;, line 49, in save
   |     return self._save(name, content)
   |   File &quot;/usr/local/lib/python3.8/site-packages/django/core/files/storage.py&quot;, line 236, in _save
   |     os.makedirs(directory)
   |   File &quot;/usr/local/lib/python3.8/os.py&quot;, line 213, in makedirs
   |     makedirs(head, exist_ok=exist_ok)
   |   File &quot;/usr/local/lib/python3.8/os.py&quot;, line 213, in makedirs
   |     makedirs(head, exist_ok=exist_ok)
   |   File &quot;/usr/local/lib/python3.8/os.py&quot;, line 223, in makedirs
   |     mkdir(name, mode)
   | PermissionError: [Errno 13] Permission denied: '/code/static'
  </code></pre>