[Fixed]-Can Django run on Gunicorn alone (no Apache or nginx)?

16πŸ‘

βœ…

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.

πŸ‘€lprsd

14πŸ‘

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.

πŸ‘€Mark Lavin

8πŸ‘

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.

πŸ‘€Andbdrew

7πŸ‘

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?

πŸ‘€hurturk

2πŸ‘

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.

πŸ‘€alanjds

Leave a comment