Docker and Django PermissionError: [Errno 13] when running collectstatic

Viewed 304

Django version: 3.2.5

Python Image: python:3.9-alpine3.14

Nginx Image: nginxinc/nginx-unprivileged:1-alpine

Docker version: 18.09.1, build 4c52b90

I am trying to configure my application to to use static files served via an Nginx proxy image within Docker.

(Apologies if I explain this badly, I will explain it as well as I currently know how.)

I have set up a volume within my docker-compose-prod.yml with the aim of serving static content here via those volumes and nginx. As part of that I have added the creating of the volumes to Dockerfile and edited the urls.py and settings.py to look for the relevant url patterns and set the STATIC_ROOT.

The application builds fine but when I run docker compose -f docker-compose-prod.yml up I get a looping error conatining multiple references to collectstatic.py and with the error:

PermissionError: [Errno 13] Permission denied: '/app/app/static/admin/css/nav_sidebar.css'

Full stack trace is below.

I have run chown -R 755 richard:richard on my home system just to be sure but this had no effect.

collectstatic is run via a /static/run.sh script in the root of my project and is initialised from my Dockerfile.

From what i understand, collectstatic should be going through each of my apps and collecting all the content from the static folders and moving it to the volume I have set up.

However the '/app/app/static/admin/css/nav_sidebar.css' file being refernced does not even exist at that location.

➜  main-website git:(master) ✗ ls -la app/app/static/admin/css/nav_sidebar.css 
ls: cannot access 'app/app/static/admin/css/nav_sidebar.css': No such file or directory
➜  main-website git:(master) ✗ ls -la app/app/static/admin/css/               
total 112
drwxr-xr-x 3 richard richard  4096 Jul 14 15:37 .
drwxr-xr-x 6 richard richard  4096 Jul 14 15:37 ..
-rwxr-xr-x 1 richard richard  8440 Jul 14 15:37 autocomplete.css
-rwxr-xr-x 1 richard richard 16378 Jul 14 15:37 base.css
-rwxr-xr-x 1 richard richard  6190 Jul 14 15:37 changelists.css
-rwxr-xr-x 1 richard richard   412 Jul 14 15:37 dashboard.css
-rwxr-xr-x 1 richard richard   423 Jul 14 15:37 fonts.css
-rwxr-xr-x 1 richard richard  8518 Jul 14 15:37 forms.css
-rwxr-xr-x 1 richard richard  1233 Jul 14 15:37 login.css
-rwxr-xr-x 1 richard richard 18052 Jul 14 15:37 responsive.css
-rwxr-xr-x 1 richard richard  1921 Jul 14 15:37 responsive_rtl.css
-rwxr-xr-x 1 richard richard  3808 Jul 14 15:37 rtl.css
drwxr-xr-x 3 richard richard  4096 Jul 14 15:37 vendor
-rwxr-xr-x 1 richard richard 10322 Jul 14 15:37 widgets.css

So I guess my question is in effect twofold:

  1. Is the issue the nav_sidebar.css file?

OR

  1. Is there another issue with my config?

run.sh

#!/bin/sh

set -e

ls -la /vol/
ls -la /vol/web

whoami

python manage.py collectstatic --noinput

uwsgi --socket :9000 --workers 4 --master --enable-threads --module app.wsgi 

Project Layout

├── app
│   ├── about
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── __init__.py
│   │   ├── migrations
│   │   ├── models.py
│   │   ├── __pycache__
│   │   ├── tests.py
│   │   ├── urls.py
│   │   └── views.py
│   ├── app
│   │   ├── asgi.py
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   ├── settings.py
│   │   ├── static
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── contact
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── __init__.py
│   │   ├── migrations
│   │   ├── models.py
│   │   ├── __pycache__
│   │   ├── tests.py
│   │   ├── urls.py
│   │   └── views.py
│   ├── home
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── __init__.py
│   │   ├── migrations
│   │   ├── models.py
│   │   ├── __pycache__
│   │   ├── tests.py
│   │   ├── urls.py
│   │   └── views.py
│   ├── manage.py
│   ├── privacy
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── __init__.py
│   │   ├── migrations
│   │   ├── models.py
│   │   ├── __pycache__
│   │   ├── tests.py
│   │   ├── urls.py
│   │   └── views.py
│   ├── static
│   │   ├── app
│   │   ├── css
│   │   ├── images
│   │   └── scripts
│   └── templates
│       ├── about.html
│       ├── contact.html
│       ├── footer.html
│       ├── header.html
│       ├── home.html
│       ├── layout.html
│       ├── privacy.html
│       └── slider.html
├── data
│   └── web
├── docker-compose-prod.yml
├── docker-compose.yml
├── Dockerfile
├── LICENSE
├── proxy
│   ├── default.conf.tpl
│   ├── Dockerfile
│   ├── run.sh
│   └── uwsgi_params
├── requirements.txt
└── scripts
    └── run.sh

docker-compose-prod.yml

version: "3.9"

services:
  app:
    build: 
      context: .
    restart: always
    volumes:
      - static-data:/vol/web
    environment: 
      - SECRET_KEY=${SECRET_KEY}
      - ALLOWED_HOSTS=${ALLOWED_HOSTS}
  
  proxy:
    build: 
      context: ./proxy
    restart: always
    depends_on: 
      - app
    ports:
      - 80:8000
    volumes:
      - static-data:/vol/static
  
volumes:
  static-data:

My nginx config is stored in the /proxy/default.conf.tpl file:

server {
    listen ${LISTEN_PORT};

    location /static {
        alias /vol/static;
    }

    location / {
        uwsgi_pass              ${APP_HOST}:${APP_PORT};
        include                 /etc/nginx/uwsgi_params;
        client_max_body_size    10M;
    }
}

When my Dockerfile runs it creates the /vol/web/static folder:

RUN python -m venv /py && \
    /py/bin/pip install --upgrade pip && \
    apk add --update --no-cache --virtual .build-deps \
    build-base \
    gcc \
    linux-headers && \
    /py/bin/pip install -r /requirements.txt && \
    apk del .build-deps && \
    adduser --disabled-password --no-create-home rsecuser && \
    mkdir -p /vol/web/static && \
    chown -R rsecuser:rsecuser /vol && \
    chmod -R 755 /vol && \
    chmod -R +x /scripts

settings.py

PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))

STATIC_URL = '/static/static/'
STATIC_ROOT = '/vol/web/static'

STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')

urls.py

from django.contrib import admin
from django.urls import path, include
from django.views.generic import RedirectView
from django.conf.urls.static import static
from django.conf import settings


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', RedirectView.as_view(url='home/', permanent=True)),
    path('home/', include('home.urls')),
    path('about/', include('about.urls')),
    path('contact/', include('contact.urls')),
    path('privacy/', include('privacy.urls')),
] 

Stack trace

main-website_app_1 exited with code 1
app_1    | Traceback (most recent call last):
app_1    |   File "/app/manage.py", line 21, in <module>
app_1    |     main()
app_1    |   File "/app/manage.py", line 17, in main
app_1    |     execute_from_command_line(sys.argv)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
app_1    |     utility.execute()
app_1    |   File "/py/lib/python3.9/site-packages/django/core/management/__init__.py", line 413, in execute
app_1    |     self.fetch_command(subcommand).run_from_argv(self.argv)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/management/base.py", line 354, in run_from_argv
app_1    |     self.execute(*args, **cmd_options)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/management/base.py", line 398, in execute
app_1    |     output = self.handle(*args, **options)
app_1    |   File "/py/lib/python3.9/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 187, in handle
app_1    |     collected = self.collect()
app_1    |   File "/py/lib/python3.9/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 114, in collect
app_1    |     handler(path, prefixed_path, storage)
app_1    |   File "/py/lib/python3.9/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 348, in copy_file
app_1    |     self.storage.save(prefixed_path, source_file)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/files/storage.py", line 54, in save
app_1    |     return self._save(name, content)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/files/storage.py", line 274, in _save
app_1    |     fd = os.open(full_path, self.OS_OPEN_FLAGS, 0o666)
app_1    | PermissionError: [Errno 13] Permission denied: '/app/app/static/admin/css/nav_sidebar.css'
app_1    | Traceback (most recent call last):
app_1    |   File "/app/manage.py", line 21, in <module>
app_1    |     main()
app_1    |   File "/app/manage.py", line 17, in main
app_1    |     execute_from_command_line(sys.argv)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
app_1    |     utility.execute()
app_1    |   File "/py/lib/python3.9/site-packages/django/core/management/__init__.py", line 413, in execute
app_1    |     self.fetch_command(subcommand).run_from_argv(self.argv)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/management/base.py", line 354, in run_from_argv
app_1    |     self.execute(*args, **cmd_options)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/management/base.py", line 398, in execute
app_1    |     output = self.handle(*args, **options)
app_1    |   File "/py/lib/python3.9/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 187, in handle
app_1    |     collected = self.collect()
app_1    |   File "/py/lib/python3.9/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 114, in collect
app_1    |     handler(path, prefixed_path, storage)
app_1    |   File "/py/lib/python3.9/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 348, in copy_file
app_1    |     self.storage.save(prefixed_path, source_file)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/files/storage.py", line 54, in save
app_1    |     return self._save(name, content)
app_1    |   File "/py/lib/python3.9/site-packages/django/core/files/storage.py", line 274, in _save
app_1    |     fd = os.open(full_path, self.OS_OPEN_FLAGS, 0o666)
app_1    | PermissionError: [Errno 13] Permission denied: '/app/app/static/admin/css/nav_sidebar.css'
main-website_app_1 exited with code 1
0 Answers
Related