How to debug django staticfiles served with whitenoise, gunicorn, and heroku?

Viewed 599

I've got a project that runs on Heroku from a Dockerfile and heroku.yml.

The site generally works, but I am having trouble with static files.

collectstatic is run when building the pack.

If I set DEBUG to True, it finds the files.

I'm trying to use whitenoise but not sure why it's not working. It sounds so simple so I'm sure it's something silly.

heroku.yml

setup:
    addons:
        - plan: heroku-postgresql
build:
    docker:
        web: Dockerfile
release:
    image: web
    command:
        - python manage.py collectstatic --noinput
run:
    web: gunicorn records_project.wsgi

settings.py

MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.contrib.sites.middleware.CurrentSiteMiddleware',
]
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'whitenoise.runserver_nostatic',
    'django.contrib.staticfiles',
    'django.contrib.sites',
    ... more stuff here...
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# for referencing files with a URL
STATIC_URL = '/static/'
# where to find static files when local
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]
# location of satatic files for production
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# how Django should look for static file directories; below is default
STATICFILES_FINDERS = [
    # defaults
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
]
# This gives me a 500 error
# STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

urls.py

urlpatterns here...
...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
4 Answers

Any chance you are referencing a static file (e.g., a CSS file or image) in your template that doesn't exist? I was having this same problem because I had the following in my base template:

<link rel="stylesheet" href="{% static 'css/styles.css' %}"> 

But no styles.css file in my css folder.

I had similar issue because static files, collected on release stage, were missing on run. So i changed my code to:

heroku.yml

setup:
  addons:
    - plan: heroku-postgresql
build:
  docker:
    web: Dockerfile
release:
  image: web
  command:
    - chmod u+x entrypoint_heroku.sh
run:
  web: ./entrypoint_heroku.sh

Dockerfile

FROM python:3.7

WORKDIR /usr/src/app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apt-get update
RUN apt install -y netcat

RUN pip install pipenv
COPY Pipfile* /usr/src/app/
RUN pipenv install --system --dev

COPY . /usr/src/app/

RUN mkdir -p /storage/static/

entrypoint_heroku.sh

#!/bin/sh
python manage.py migrate --noinput
python manage.py collectstatic --noinput
gunicorn app.wsgi

settings.py

STATIC_URL = '/static/'
MEDIA_ROOT = '/storage/'
STATIC_ROOT = MEDIA_ROOT + 'static/'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

Not the best solution. But it helped me to run server with Debug=False

For what it's worth, I never found a way to get WhiteNoise to serve those static files. I swear it's worked in the past with a similar set up, so that will remain a mystery.

I received a tip from Matt from justdjango.com that Heroku doesn't want to serve static files from that same server. Once I moved my static files over to an AWS S3 bucket, all was well.

I also faced this issue. Although successfully collecting static files on release stage, they weren't present when dyno was up (thus Django missing manifest errors).

This setup worked:

heroku.yml

build:
  docker:
    web: Dockerfile
run:
  web: ./heroku_entrypoint.sh

Dockerfile

--- some code ---

RUN chmod +x heroku_entrypoint.sh
RUN mkdir -p /app/static/

--- other code ---

heroku_entrypoint.sh

python manage.py collectstatic --noinput
python manage.py migrate
gunicorn app.wsgi:application --bind 0.0.0.0:$PORT
Related