简体   繁体   中英

Can Django run on Gunicorn alone (no Apache or nginx)?

I have tried just about every django + nginx tutorial on the web and I cannot get an image file to display on the screen. It's always the old story - 404 PAGE NOT FOUND . The web page loads fine but django.png in my /static/ folder does not. Not sure if it's a problem in settings.py or with nginx.

I am so frustrated with it that I refuse to look at another "How to get nginx/django tutorial". If I deploy a website in the near future will Gunicorn suffice to run a Django site and serve static files simultaneously without using Apache or nginx? Is there a big benefit to having a reverse proxy in the first place?

The Gunicorn documentation notes that without a proxy buffering slow clients, the default worker is susceptible to a denial of service attack: http://gunicorn.org/deploy.html

Although there are many HTTP proxies available, we strongly advise that you use Nginx. If you choose another proxy server you need to make sure that it buffers slow clients when you use default Gunicorn workers. Without this buffering Gunicorn will be easily susceptible to denial-of-service attacks. You can use slowloris to check if your proxy is behaving properly.

This might not be the case when using one of the async workers such as gevent or tornado.

Yes. Gunicorn can serve your static too.

If all else fails, let django do it for you (although, do this as a last resort before frustration.) To do that, you just have to add another url pattern, as follows:

urlpatterns = patterns('',
    # ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

While django serving static is better than not serving it at all, it is worth delegating that to the servers optimized for the same like nginx.

I'd recommend running nginx on a different port to start with, and change the django STATIC_URL setting to include the port (After you have confirmed that the port serves the statics). - Doing this is as simple as doing a simlink to the MEDIA_ROOT from the nginx folder.

And if you are using nginx anyway, it is also good to proxy all requests using it and only pass the django request to the gunicorn. All this requires is the addition of a conf file that tells nginx accordingly.

I can see how it can be confusing to those who are starting and trying to do all (proxy requests, serve static, configure nginx) at once. Try it one by one. Get the media from the gunicorn; Then serve it from nginx and then eventually have the nginx proxy too. But do this all before you have your app in production. This approach, I have seen increases understanding and decreases frustration.

If you are already using amazon web services, you can use s3 buckets to host your static content and deploy your app to ec2 using gunicorn (or whatever you want). That way, you don't have to worry about setting up your own static file server at all.

I recommend using Nginx in front for several reasons:

  • Maintenance or internal server error page can be easily implemented when gunicorn is down. That means you will always have something to respond if your application server is not running.
  • As Gunicorn doc suggests, http attacks such as DOS are not detected.
  • You may want to implement your own load-balancing strategy later on. This will become more important for release engineering as your project scales. Personally, I've found AWS ELB a bit unreliable and I'm thinking about it.

Update :

Also, please see a well written answer by a Gunicorn developer:

Why do I need Nginx and something like Gunicorn?

I made by using a Werkzeug middleware. Is not beautiful, nor performant as using an nginx server, but does the job:

Set STATIC_ROOT on settings.py

# project/settings.py
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__)))
STATIC_ROOT = BASE_DIR+'/static-collected'

Than tell Werkzeug to serve files from this folder

# project/wsgi.py
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

(...)
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
(...)

import os
from werkzeug.wsgi import SharedDataMiddleware
print 'Installing WSGI static files server middleware'
application = SharedDataMiddleware(application, {
    '/static': os.path.join(BASE_DIR, 'static-collected'),
})

When DEBUG=True, Django serve the files. When DEBUG=False, Werkzeug serve files from static-collected folder. You need to run collectstatic on the server that use DEBUG=False for this to work.

Obs: For some reason, Werkzeug gives 500 for not found files, not 404. Its weird, but still works. If you know why, please comment.

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