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:
- Is the issue the
nav_sidebar.cssfile?
OR
- 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