简体   繁体   中英

Why doesn't whitenoise work with django on AWS EB Python deployments?

I am deploying a python app on AWS Elastic Beanstalk, and wrapping the wsgi application with DjangoWhiteNoise wrapper. However, I get 404 on my requests to the static files.

# wsgi.py
...
from whitenoise.django import DjangoWhiteNoise
application = DjangoWhiteNoise(application)

# settings.py
...
STATIC_URL = '/static/'
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, '..', '.staticfiles'))

# .ebextensions/01_django.config
option_settings:
  "aws:elasticbeanstalk:application:environment":
    DJANGO_SETTINGS_MODULE: "myproject.settings.aws_ebs"
    PYTHONPATH: "/opt/python/current/app:$PYTHONPATH"
  "aws:elasticbeanstalk:container:python":
    WSGIPath: "myproject/wsgi.py"
container_commands:
  01_migrate:
    command: "django-admin.py migrate --noinput"
    leader_only: true
  02_collectstatic:
    command: "django-admin.py collectstatic --noinput"

Is there something I'm missing out here?

This is not easy to catch. However, apache is serving the wsgi application, and if you grep for static in /etc/httpd you will see something suspicius.

[ec2-user@ip-1-1-1-1 ~]$ cd /etc/httpd/
[ec2-user@ip-1-1-1-1 httpd]$ find . -type f -exec grep static {} +
./conf.d/wsgi.conf:Alias /static/ /opt/python/current/app/static/
./conf.d/wsgi.conf:<Directory /opt/python/current/app/static/>

More in depth, inside of the wsgi.conf file:

Alias /static/ /opt/python/current/app/static/
<Directory /opt/python/current/app/static/>
Order allow,deny
Allow from all
</Directory>

This means that requests to /static/some/resource.css will never reach the wsgi application, and the files does not exist in /opt/python/current/app/static/, so it will return 404.

There are a few options to solve this :)

1. Skip WhiteNoise and just serve the files via apache.

Remove the two last lines in wsgi.py, so that you just use the django wsgi application. Also change the below:

# settings.py - set the storage to use djangos built in ManifestStaticFilesStorage
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

# .ebextensions/01_django.conf - add this to option_settings section
  "aws:elasticbeanstalk:container:python:staticfiles":
    "/static/": ".staticfiles/"

The drawback with this solution is that the files will not be compressed. However, you will anyways probably use some sort of CDN for your static files, and then the compression of the files will not be any problem. AWS CloudFront is one example of CDN you can use to enable compression of static files.

2. Set STATIC_URL = '/staticfiles/'

Change STATIC_URL to be something else that '/static/', for example '/staticfiles/', this way there will not be any match to the '/static/' alias, and django will serve the static files, not apache.

Side notes

Unfortunally it looks the AWS EB Python environment doesn't allow you to remove the /static/ Alias, neither using eb command line tool, nor using the Web interface. Take a look here:

AWS Web Console AWS Elastic Beanstalk Python配置

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM