Ashiqur Rahman
Posted on January 18, 2021
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
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;
}
}
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;
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
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'
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:
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
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
now to connect to our docker containers:
docker exec -it <CONTAINER_ID> sh
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.
Posted on January 18, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.