Serve Static Files by Nginx from Django using Docker
Nov 02, 2016 · 2 Min Read · 7 Likes · 23 Comments
This is more of a follow up post of my previous article.
Before I start, I am assuming you have successfully deployed django using docker and nginx, but having some problems serving static files.
Steps
No worries, it is easy. Just follow these steps:
1. In your django settings.py file, add static file directory i.e. STATIC_ROOT=/static
. So what it will do is, when you run collectstatic
command(python manage.py collectstatic
), it will store the static files in your /static directory of OS.
2. Now in docker-compose.yml
folder, lets add a configuration like this:
version: "2"
services:
nginx:
image: nginx:latest
container_name: NGINXDOCKERNAME
ports:
- "8000:8000"
volumes:
- ./src:/src
- ./config/nginx:/etc/nginx/conf.d
- /static:/static <--- HERE
depends_on:
- web
web:
build: .
container_name: DJANGOXDOCKERNAME
command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn mydjango.wsgi -b 0.0.0.0:8000"
depends_on:
- db
volumes:
- ./src:/src
- /static:/static <---- HERE
expose:
- "8000"
db:
image: postgres:latest
container_name: PSQLDOCKERNAME
FYI the command
argument of the docker compose is same as CMD
of Dockerfile. So we can move this inside Dockerfile if we want to(i.e.: CMD python manage.py makemigrations;python manage.py migrate;gunicorn mydjango.wsgi -b 0.0.0.0:8000
).
What it will do is that, two containers web and nginx will share a directory named /static.
3. Now lets add few lines in nginx’s config file, i.e mydjango.conf
:
upstream web {
ip_hash;
server web:8000;
}
server {
location /static/ {
autoindex on;
alias /static/;
}
location / {
proxy_pass http://web/;
}
listen 8000;
server_name localhost;
}
So what it will do is, any request to url like yourhost:yourport/static/*
this comes to nginx, it will serve data from /static
directory.
4. Now lets run the following command:
docker exec DOCKERNAME /bin/sh -c "python manage.py collectstatic --noinput"
Or update the command
key’s value in compose to:
command: bash -c "python manage.py collectstatic --no-input && python manage.py makemigrations && python manage.py migrate && gunicorn mydjango.wsgi -b 0.0.0.0:8000"
It will put static files in /static
directory and thats should do the trick. Whenever you hit url with /static
will serve static files from that folder. Similarly you can serve media files too. Codes have been updated here at: https://github.com/ruddra/docker-django Cheers!!
Update
If you are interested to run distributed tasks using celery in Docker with Django, then please read this post.
Last updated: Feb 24, 2025
docker exec dg01 bash -c “python manage.py collectstatic –noinput” This worked for me, not the collectstatic command in the guide
just kidding this still doesn’t work for me
Did you solved it?
Did you?
@disqus_NRx0k3reSp:disqus from where you have your .yml file try running: docker-compose run <django_container_name> python manage.py collectstatic. This might also help: https://docs.docker.com/com… bon chance
I added:
RUN python manage.py collectstatic --noinput
to my Dockerfile and it works fine on the web service but the Volume /static still empty in the ngnix service. How can I do to get /static from web copied to /static on nginx ?As far as I know, it should share the directory. I will look into it
Hi - I’m curious about why in this example the nginx mydjango.conf file specifies
listen 8001;
while in your previous example it waslisten 8000;
I don’t think its a big deal, you can change it to :8000 😄
So your code doesn’t work… and it’s ok.. ?
Hi, The code should be working, and if you need working example, please follow the github link given with the post. Hope it helps 😄 .
You can ommit/skip step 2. It is not required. Just make sure that in step 3 the alias is the whole path (here /src/static, or in general $WORKDIR/STATIC_ROOT or $WORKDIR/MEDIA_ROOT) and location matches STATIC_URL or MEDIA_URL.
thanks for the post. This helped me a lot!
I’ve based my current project on the information posted here and it has worked great until I tried deploying my project using docker-machine. It seems like the src-folder containing my app isn’t created properly when running on the remote docker instance but the folders for nginx, which is shared between the djangoproject and nginx are created ok. If I do the exact same and run docker-compose build && docker-compose up locally or log in using ssh and do it on the server it runs just fine. Deploying using docker-machine was sort of the idea to solve my deployment problems so an article based on this one but deploying using docker-machine would be great. Keep up the great work! :-)
You’re a lifesaver!
I notice your docker-compose.yml has version:2. I was trying to follow this with version:3, and I was getting errors of
I ended up changing my docker-compose.yml to use a top-level named volume. So, instead of putting in
in web and nginx, I put in
And at the end of the docker-compose.yml file, I added
And it all worked! Thanks for the great tutorials!
Thanks for the tutorial. While i was trying to enter docker exec DOCKERNAME /bin/sh -c ‘python manage.py collectstatic –noinput’ Error: No such container: NGINXDOCKERNAME
This post was a real life server for me. I had been using using uwsgi only to serve my app and the statics and was wondering how to serve the statics with nginx since nginx was on the host OS, and the django app in a docker container.
I am getting the following error. Can you please help me resolve it
nginx01 | nginx: [emerg] host not found in upstream “web:8000” in /etc/nginx/conf.d/mydjango.conf:3 nginx01 exited with code 1
I am getting the following error. Can you please help me resolve it
nginx01 | nginx: [emerg] host not found in upstream “web:8000” in /etc/nginx/conf.d/mydjango.conf:3 nginx01 exited with code 1
Thank you. It was helpful a lot!!!
Any pointers on multiple django projects all being fronted by the same NGINX container, but in such a way that they are not each trying to claim the root of the server?
Very helpful tutorial. thank you.
Got stuck on an error for a while
django.db.utils.OperationalError: could not translate host name "db" to address: Temporary failure in name resolution
After some digging I realized I was down a few dependencies for psycopg2 for those using PostgreSQL
https://www.psycopg.org/docs/install.html#build-prerequisites