Goal: The set of docker containers for a production django website deployment.
My hang up in this process is that usually nginx directly serves the static files... Based on my understanding of a good architecture using docker, you would have a container for your wsgi server (probably gunicorn), a separate nginx container with an upstream server configuration pointing to your gunicorn container. The nginx container can load balance between multiple gunicorn containers.
But what this implies is that I have to install my django app's static files in the nginx container, which seems like bad practice since it's primary goal is really load balancing
Is it better to have three containers: nginx, gunicorn, and a dedicated static server (possibly nginx or lighthttpd) for static files?
With reference to serving static files, your options depend on the functionality of your application. There's a very nifty tool called dj-static
which will help you serve static files by adding very minimal code.
The documentation is fairly simple and all you have to do is follow these steps.
I found this answer from Michael Hampton: "This only works if the processes are in the same host, VM or container, because it tries to make a connection to the same machine. When they are in different containers, it does not work.
You need to alter your nginx configuration so that it uses the internal IP address of the uwsgi container." Link from the post
And definitely is something you have to keep in mind if you will have Nginx in a different container, also you have to set the nginx.conf, pointing your statics file directory as alias preventing a security issue.
I hope this code work for everybody, it took me a couple of ours to figure about how to compose Gunicorn, docker, and Nginx:
# nginx.conf
upstream djangoA {
server $DOCKER_CONTAINER_SERVICE:9000 max_fails=3 fail_timeout=0;
# In my case looks like: web:9000
}
Server {
include mime.types;
# The port your site will be served on
listen 80;
# the domain name it will serve for
server_name $YOUR_SERVER_NAME;# substitute your machine's IP address or FQDN
charset utf-8;
#Max upload size
client_max_body_size 512M; # adjust to taste
location /site_media {
alias $DIRECTORY_STATIC_FILES/site_media;#your Django project's media files have to be inside of the container have nginxs, you can copy them with volumes.
expires 30d;
}
location / {
try_files $uri @proxy_to_app;
}
# Finally, send all non-media requests to the Django server.
location @proxy_to_app {
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://djangoA;
}
}
And for the docker-compose:
#production.yml
version: '2'
services:
db:
extends:
file: base.yml
service: db
nginx:
image: nginx:latest
volumes:
- ./nginx:/etc/nginx/conf.d/
- ./$STATIC_FILE_ROOT/site_media:/$STATIC_FILE_ROOT/site_media
ports:
- "80:80"
depends_on:
- web
web:
extends:
file: base.yml
service: web
build:
args:
- DJANGO_ENV=production
command: bash -c "python manage.py collectstatic --noinput && chmod 775 -R project/site_media/static && gunicorn project.wsgi:application"
volumes:
- ./$DIRECTORY_APP:/$DIRECTORY_APP
ports:
- "9000:9000"
depends_on:
- db
volumes:
db_data:
external: true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With