Django serve media files in production using nginx

How to serve media file in Django production environment

by: AWS November 16,2022 last update: 1 month, 3 weeks Django Nginx

Django does not server media files itself, this is the responsibility of whichever web server you are using in production.

The best options are:

    1. Nginx
    2. Apache

In this tutorial we will check how to serve media files in production environment using Nginx web server.

First let's explain the existing problem  

While working in dev environment you can add this settings to your settings.py files and url to your main django url.py file in order to serve media files

    • Here you are telling django where the media files are stored 
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
    • And this is the url which will be used to serve the media files (it should be added to the bottom of your main url.py file)
if settings.DEBUG == True:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

As you might noticed this is applicable only while DEBUG setting is set to True.

But when we switch to production and set the DEBUG setting to False, you will notice that all media files won't be served and you will receive a 500 error response.

and this is because Django is not serving the media files anymore. 

because in production env all requests will be handled by Nginx, so Nginx is responsible to serve the media files 

Let's dive deeper and see how this is happening

    1. The first time you open the website a request will be sent from the browser to Nginx 
    2. Nginx will forward the request to Django
    3. Django will generate the response and send it back to Nginx
    4. Nginx will send back the response to the browser
    5. Now the browser will parse the HTML file in order to render it and when it reaches the img tags it will trigger another request using the img tag src url  which will be something like src="https://domain.com/media/thumbnail/image.png" 
    6. Nginx will receive the request, but it cannot serve the image file because it's not configured to serve media file

 Configure Nginx 

In order to allow nginx to serve media file 

we need to add the following (the one in bold) in the config file that contains Django configuration.

server {
    server_name domain.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        alias /home/ubuntu/django/static/;
    }

    location /media {
        autoindex on;
        alias /home/system_user/project_name/media/; #this should be the path to your media folder
    }

After that you just need to restart your server in order to apply the changes

sudo service nginx restart 

and that's it, Nginx is supposed to serve your media files now