Issue: Collecting static files with Django fails in Dockerfile, but works in Heroku release command.
When deploying a Django app to Heroku using Docker, the RUN manage.py collectstatic --noinput
command in the Dockerfile fails because there is no value set for the environment variable DJANGO_SECRET_KEY
.
However, when the collectstatic
command is run as a release command, it works without error, but the app returns a 500 error when the URL is hit because the copied files are not found on the ephemeral filesystem.
Solution:
To solve this issue, the collectstatic
command needs to be run in the Heroku release command instead of the Dockerfile. The settings for collectstatic
should be included in settings.py
, as shown in the following example:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
...
]
...
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
STATICFILES_STORAGE = 'backend.storage.WhiteNoiseStaticFilesStorage'
The Dockerfile should create a staticfiles
directory and copy the static files to it.
# Pull base image
FROM python:3.7-slim
# Set environment varibles
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Set work directory
RUN mkdir /code
WORKDIR /code
# Install dependencies
RUN pip install pipenv
COPY Pipfile Pipfile.lock /code/
RUN pipenv install --system
# Copy project
COPY . /code/
## create staticfiles directory
RUN mkdir backend/staticfiles
The Heroku release command should run collectstatic
to copy the files to the directory created earlier:
heroku.yml
build:
docker:
web: Dockerfile
run:
web: gunicorn backend.config.wsgi:application --bind 0.0.0.0:$PORT
release: python manage.py collectstatic --noinput