Add nginx as a option like whitenoise, google storage and aws to handle static only would be cool.
The current options require third party connections / configuration to work ..
While this is not fully enforced by whitenoise, it is highly recommended.
I saw that in the past, nginx was used, but it was tricky to implement lets encrypt, but using nginx behind traefik would not be a problem, since it does not have to handle ssl. Also, no third party configs are required.
@marciks
Hello, I thought the same thing as you about 2 months ago for a small project, I created a version that allows to have nginx that serves media and static files, the problem is that I couldn't 'scale' the docker since it is directly linked to the django container, there would be the possibility by making a docker who only shares files, but I found a better alternative that is much simpler and does not require a big change in django cookie cutter, The use of "MINIO" that has exactly the same "API" as amazon, I share from a cache.domainname.com, there is a little hack to do at the settings level but nothing complicated :)
example .env/.production/.django:
# AWS
# ------------------------------------------------------------------------------
DJANGO_AWS_ACCESS_KEY_ID=key
DJANGO_AWS_SECRET_ACCESS_KEY=key
DJANGO_AWS_STORAGE_BUCKET_NAME=namebucket
DJANGO_AWS_S3_ENDPOINT_URL=https://cache.domainname.com
example setting:
# STORAGES
# ------------------------------------------------------------------------------
# https://django-storages.readthedocs.io/en/latest/#installation
INSTALLED_APPS += ["storages"] # noqa F405
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID")
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY")
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME")
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_QUERYSTRING_AUTH = False
# DO NOT change these unless you know what you're doing.
_AWS_EXPIRY = 60 * 60 * 24 * 7
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_S3_OBJECT_PARAMETERS = {
"CacheControl": f"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate"
}
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_DEFAULT_ACL = None
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None)
# STATIC
# ------------------------
STATICFILES_STORAGE = "config.settings.production.StaticRootS3Boto3Storage"
COLLECTFAST_STRATEGY = "collectfast.strategies.boto3.Boto3Strategy"
AWS_S3_ENDPOINT_URL = env("DJANGO_AWS_S3_ENDPOINT_URL", default=None)
AWS_S3_USE_SSL = True
AWS_AUTO_CREATE_BUCKET = True
STATIC_URL = f"{AWS_S3_ENDPOINT_URL}/{AWS_STORAGE_BUCKET_NAME}/static/"
# MEDIA
# ------------------------------------------------------------------------------
# region http://stackoverflow.com/questions/10390244/
# Full-fledge class: https://stackoverflow.com/a/18046120/104731
from storages.backends.s3boto3 import S3Boto3Storage # noqa E402
class StaticRootS3Boto3Storage(S3Boto3Storage):
location = "static"
default_acl = "public-read"
class MediaRootS3Boto3Storage(S3Boto3Storage):
location = "media"
file_overwrite = False
# endregion
DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage"
MEDIA_URL = f"{AWS_S3_ENDPOINT_URL}/{AWS_STORAGE_BUCKET_NAME}/media/"
@scwall Thanks for your tip! I actually wanted to avoid the configuration on third party services like gcloud, AWS or cloud flare just for serving static.. the only way to do this is by using a webserver (which traefik is not).. also, I think that it is possible to run in a separate container! This answer on stackoverflow explains it a little bit: https://stackoverflow.com/a/51903852/8213102
@marciks my network situation required the same thing. Here's what I added to this project to serve static files from a docker volume.
Note: for convenience I use dockerhub's base nginx image, it was super easy plug and play.
docker volume create {VOLUME_CONFIG_PARAMS} {DOCKER_VOLUME}
In this example DOCKER_VOLUME_TARGET was the name of the directory within the container that contains the static files.
production.yml additions
nginx:
image: nginx
volumes:
- {DOCKER_VOLUME}:/usr/share/nginx/html/{DOCKER_VOLUME_TARGET}
ports:
- "8099:80"
The only nginx config needed is mapping the docker volume to the default /usr/share/nginx/html/ location and mapping the default external port to an internal port 80 so that nginx can act as a webserver. It can't have an external port because traefik is using that.
In .django config
DJANGO_STATIC_ROOT=/{DOCKER_VOLUME_TARGET}/staticfiles/
traefik.toml additions
[file]
[backends]
[backends.django]
[backends.django.servers.server1]
url = "http://django:5000"
[backends.nginx]
[backends.nginx.servers.server1]
url = "http://nginx"
.
.
.
[frontends.nginx]
backend = "nginx"
passHostHeader = true
[frontends.nginx.routes.dr1]
rule = "{HOST};PathPrefix:/{DOCKER_VOLUME_TARGET}/staticfiles"
You may have already finished your solution by now, but let me know if there's anything I can clarify, and good luck!
Hey @nickdnickd! I have found everything I needed in this repo: https://github.com/umputun/nginx-le
I will be using nginx instead of traefik..
Thanks for your help though! For clients, less registration is better and in case I need django cookiecutter, I will definitely use your work around
Most helpful comment
@marciks my network situation required the same thing. Here's what I added to this project to serve static files from a docker volume.
Note: for convenience I use dockerhub's base nginx image, it was super easy plug and play.
Create a docker volume to the files you want to serve
docker volume create {VOLUME_CONFIG_PARAMS} {DOCKER_VOLUME}In this example DOCKER_VOLUME_TARGET was the name of the directory within the container that contains the static files.
Add the nginx container
production.yml additions
The only nginx config needed is mapping the docker volume to the default /usr/share/nginx/html/ location and mapping the default external port to an internal port 80 so that nginx can act as a webserver. It can't have an external port because traefik is using that.
Tell Django to look here for static files
In .django config
DJANGO_STATIC_ROOT=/{DOCKER_VOLUME_TARGET}/staticfiles/Finally connect this in to Traefik
traefik.toml additions
You may have already finished your solution by now, but let me know if there's anything I can clarify, and good luck!