Paul Gilmartin
Paul Gilmartin

Reputation: 72

Nginx failing to serve django static or media files on digital ocean

I'm having issues serving static files and media files when I deploy my dockerised django app to digital ocean. I've read many similar questions on here, but none of the answers have worked for me so far.

Roughly following this guide, https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/#nginx, I'm now in a state where I can spin up my docker container locally using the following commands and have nginx serve static/media files perfectly:

sudo docker-compose -f docker-compose-prod.yml down -v
sudo docker-compose -f docker-compose-prod.yml up -d --build
sudo docker-compose -f docker-compose-prod.yml exec web python manage.py collectstatic --no-input --clear

I'm now attempting to get the same working on a digital ocean droplet. On the remote server I run exactly the same commands as above start up the services. Everything then works as expected apart from the ability to access any static or media file. Whenever I for example visit {my digital ocean ip}/static/admin/css/nav_sidebar.css, I'm met with a 404 error. Whenever I see chrome attempting to fetch my custom css, the requests just show as "cancelled" (and then if I visit the URL path of the cancelled request I see the same 404).

My code can be seen here: https://github.com/PaulGilmartin/personal_website Parts perhaps relevant to this discussion:

nginx.conf

upstream personal_website {
    server web:8000;
}

server {

    listen 80;

    location / {
        proxy_pass http://personal_website;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }

    location /static/ {
        alias /var/www/personal_website/static/;
    }

    location /media/ {
        alias /var/www/personal_website/media/;
    }

}

settings.py

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

I'm especially confused that the exact same commands work perfectly locally. This made me think that the 404s on the remote server are a permission based symptom, but I don't see how that can be the case as in my Dockerfile.prod I'm careful to chown everything to the non-root user.

Any help would be greatly appreciated as I'm running low on ideas of what the issue could be!

Edit: Here's my docker-compose file:

version: '3.7'


services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.prod
    command: gunicorn personal_website.wsgi:application --bind 0.0.0.0:8000 --timeout 120
    volumes:
      - static_volume:/var/www/personal_website/static
      - media_volume:/var/www/personal_website/media
    env_file:
      - ./.env.prod
    expose:
      - 8000
    ports:
      - "80:8000"
    depends_on:
      - db
  db:
    image: postgres:11
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env.prod.db
  nginx:
    build: ./nginx
    volumes:
      - static_volume:/var/www/personal_website/static
      - media_volume:/var/www/personal_website/media
    ports:
      - 1337:80
    depends_on:
      - web

volumes:
  postgres_data:
  static_volume:
  media_volume:

Upvotes: 2

Views: 1776

Answers (1)

Egor Wexler
Egor Wexler

Reputation: 1944

I have a feeling that the issue is here:

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

This path should actually be the same as nginx expecting:

/var/www/personal_website/static/

Thus, you can try the following things:

  1. Try to hardcode static root in Django settings:

    STATIC_ROOT = '/var/www/personal_website/static/'

  2. Do bash into the container where Django is running: docker exec -it <container_name> /bin/bash - run there collectstatic and check whether static files are copied to the folder you expected. If not - then you may want to find, where exactly the files are copied.

  3. Also check inside nginx container if it also sees the correct volume with static files

I had quite the same issue and hardcoding paths for static and media solved the issue

Update: I've cloned the project and for me, it didn't pick up static files. So I did the following changes in docker-compose-prod.yml and it became to work:

  1. Remove ports from services - web:

    ports:
       - "80:8000"
    

It is not needed as web (Django) should not be accessible from outside. Only internally in Docker on exposed port 8000

  1. Set open port of nginx to 80:

    ports:
       - 80:80
    

I don't know which port is used by DigitalOcean to host the site, but the default is 80.

Upvotes: 1

Related Questions