DEV Community

Cover image for Configuring nginx - Dockerizing Django for deploying anywhere !
Ashiqur Rahman
Ashiqur Rahman

Posted on • Updated on

Configuring nginx - Dockerizing Django for deploying anywhere !

We want to set up our web server in this part of the tutorial. So, a key issue while deploying django is serving static files. I googled a bit and there are quite a few interesting ideas floating around the internet :/ . So, it can get confusing. So, we want to resolve this RIGHT NOW. !

So in order to setup nginx, we create a new folder called 'proxy' at the same level as our src folder.

├── proxy
│   ├── default.conf
│   ├── Dockerfile
│   └── uwsgi_params
├── scripts
│   └── entrypoint.sh
└── src
    ├── myapp1
    │   ├── admin.py
    │   ├── apps.py
    │   ├── __init__.py
    │   ├── migrations
    │   │   ├── __init__.py
    │   ├── models.py
    │   ├── static
    │   │   └── myapp1
    │   │       ├── css
    │   │       │   └── test.css
    │   │       ├── img
    │   │       │   ├── test.jpg
    │   │       │   └── test2.jpg
    │   │       └── js
    │   │           ├── test.js
    │   │           └── test2.js
    │   ├── templates
    │   │   └── admin_extend
    │   │       └── index.html
    │   ├── templatetags
    │   │   ├── custom_tags.py
    │   │   ├── __init__.py
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    ├── mysite
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── myapp2
    │   ├── admin.py
    │   ├── apps.py
    │   ├── __init__.py
    │   ├── migrations
    │   │   ├── 0001_initial.py
    │   │   ├── 0002_auto_20200918_1702.py
    │   │   ├── __init__.py
    │   ├── models.py
    │   ├── serializers.py
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    ├── db.sqlite3
    ├── manage.py

Enter fullscreen mode Exit fullscreen mode

We create 3 empty files inside the proxy folder.

  • default.conf (we setup our nginx configuration here)
  • uwsgi_params (you need this for uwsgi with nginx :3 its in the official uwsgi documentation)
  • Dockerfile (docker file for our nginx container)

default.conf:

server {
    listen 80;

    location /static {
        alias /vol/static;
    }

    location / {
        uwsgi_pass app:8000;
        include /etc/nginx/uwsgi_params;
    }
}
Enter fullscreen mode Exit fullscreen mode

First, we let nginx listen to port 80 for deployment.
so, what we do is we serve any path with /static directly from nginx and we serve anything else from our uwsgi server which is running our app. Simple !

usgi_params
basically all you need to here is copy & paste this block in to your usgi_params:

uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_ADDR $server_addr;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
Enter fullscreen mode Exit fullscreen mode

its all in the documentation here

Dockerfile

FROM nginxinc/nginx-unprivileged:1-alpine

COPY ./default.conf /etc/nginx/conf.d/default.conf
COPY uwsgi_params /etc/nginx/uwsgi_params

USER root

# setup static dirs
RUN mkdir -p /vol/static
RUN chmod 755 /vol/static

USER nginx
Enter fullscreen mode Exit fullscreen mode

We use a unprivileged nginx container. This is for the same reason we mentioned earlier. We dont want to be running our docker containers with root user access. Notice, we switched to user nginx just after setting up the static dirs. This will ensure nginx will be run with the user 'nginx'

Now, we need to do a couple of things in our django settings.py before nginx can start serving our static files:

STATIC_URL = '/static/static/'
STATIC_ROOT = '/vol/web/static'

MEDIA_URL = '/static/media/' 
MEDIA_ROOT = '/vol/web/media'  
Enter fullscreen mode Exit fullscreen mode

Why? when we run our collectstatic command in our entrypoint.sh all the static files will be moved in to the STATIC_ROOT. Then, we would just map this directory to our proxy to serve the static files directly from nginx !!

Now, the last thing we need is to handle our new dockerfile in our docker-compose. So, we need to add a new service for our proxy.

version: '3.7'

services:
  app:
    build:
      context: .
    ports:
      - "8000:8000"
    volumes:
      - production_static_data:/vol/web
    restart: always
    env_file:
      - .live.env

  proxy:
    build:
      context: ./proxy
    volumes:
      - production_static_data:/vol/static
    restart: always
    ports:
      - "80:80"
    depends_on:
      - app

volumes:
  production_static_data:
Enter fullscreen mode Exit fullscreen mode

Notice, how we share our existing production_static_data docker volume between the two services. The easiest way to truly understand how this works is directly connecting to our running docker containers and see whats happening inside. Clear-as-a-day !
Run:

docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

this will build our two services 'app' & 'proxy'. Notice, we specified the 'depends_on' key in our docker-compose means the service 'proxy' depends on service 'app' and therrefore, app will be up and running first.
Now, lets find the CONTAINER_ID for the our docker containers using:

docker ps
Enter fullscreen mode Exit fullscreen mode

now to connect to our docker containers:

docker exec -it <CONTAINER_ID> sh
Enter fullscreen mode Exit fullscreen mode

this will give you shell access inside your docker container. Now, after connecting to either the 'app' or 'proxy' service, you should be able to find a folder called 'vol'. Go deeper and you should be able to find your static files in both the 'app' and 'proxy' containers. Simple !

And thats it for our nginx setup !! On the next part of this tutorial, we will start setting up a container for our database.

If you found this post helpful, CLICK BELOW 👇 Buy Me A Beer

Top comments (0)