Django serves the static files only during the development, i.e. when you run
python manage.py runserver.
In the production, it is assumed that the static files are being served by something more suitable, like a regular Web server. Having said that, in interest of keeping our backend self-contained, there is a way to serve them by using the package called
whitenoise Either way, the first step is to collect the static files from all Django apps we have (remember, our application is made of several Django apps, namely photos, admin and rest_framework).
manage.py provide the command to do that, but first we have to tweak the
settings.py a little.
Add the following at the end pf your
STATIC_URL = "/static/" STATIC_ROOT = str(BASE_LOC.path("staticfiles"))
These two settings specify that all static files will be served with the URL prefix
/static/ and the location of the collected static files should be the subdirectory
Let’s collect the static files:
python manage.py collectstatic
You will notice now that the
staticfiles directory has collected the css, png, js etc files from the rest_framework and admin apps. We are not using anywhere the static files in the photos app, so it was not created.
Now install the
whitenoise package which will allow to serve these without deferring to some web server:
pip install whitenoise
Now enable whitenoise middleware in the
aettings.py. Because of the whitenoise requirements, it must go after the
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', # new 'whitenoise.middleware.WhiteNoiseMiddleware', # ...
whitenoise is able to cash and compress the static files it serves. To enable that add the following line:
# ... STATIC_ROOT = str(BASE_LOC.path("staticfiles")) # new STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
As we are still going to run Django in the dev mode, it is a good practice to disable the magical static file serving by the Django in the dev mode and go through the whitenoise even in such scenarios. In the INSTALLED_APPS section, just before the `django.contrib.staticfiles add:
INSTALLED_APPS = [ # ... # new "whitenoise.runserver_nostatic", "django.contrib.staticfiles", # ...
Now, let’s try to run whitenoise-enabled backend in the dev mode:
python manage.py collectstatic --noinput python manage.py runserver
--noinput flag disables annoying verification questions.
Verify that http://localhost:8000/admin/ still works as expected
All right, let’s modify our Docker image to use whitenoise as well. First we need to re-capture our dependencies:
pip freeze > requirements.txt
And now, modify the
boot.sh file so it collects static files:
#!/bin/sh python manage.py collectstatic --no-input exec gunicorn pixies.wsgi:application --bind 0.0.0.0:$PORT --log-file -
Rebuild and start the containers again:
docker-compose up -d --build
Try connecting to the backend in the container at http://localhost:9090/admin/ This time it should display as expected with all css loaded.
While we are at it, let’s add the frontend to the
docker-compose.yml so we can start everything together with one command:
# ... # new frontend: build: context: ../frontend ports: - 9091:80 environment: - PORT=80 depends_on: - backend #...
Now you can start everything in the containers just by running
docker-compose up -d --build
Your frontend should be available on the port 9091: http://localhost:9091/ Of course, it still shows the pictures we have hardcoded while writing the frontend code. In the next module, we are going to start connecting the frontend to the backend, so the picture list is loaded from the backend.