mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2024-11-10 19:57:09 +03:00
Add option to serve media files locally using nginx (#2457)
* Add option to serve media files locally using nginx * Fix nginx media location and storage issue * Fix traefik django-media typo * Add certresolver property to web-media-router * Add trailing slash in nginx configuration to avoid path traversal exploits * Remove autoindexing from nginx configuration so nginx uses its default off setting * Use nginx to serve media files if cloud provider is None * Add back warning about lack of media files without Docker or Cloud providers * Update documentation * Fix typos and rephrase Co-authored-by: Arkadiusz Ryś <arkadiusz.michal.rys@gmail.com> --------- Co-authored-by: Bruno Alla <alla.brunoo@gmail.com> Co-authored-by: Bruno Alla <browniebroke@users.noreply.github.com>
This commit is contained in:
parent
46868bed26
commit
06369bfd4c
|
@ -31,7 +31,7 @@ production-ready Django projects quickly.
|
||||||
- Optional basic ASGI setup for Websockets
|
- Optional basic ASGI setup for Websockets
|
||||||
- Optional custom static build using Gulp or Webpack
|
- Optional custom static build using Gulp or Webpack
|
||||||
- Send emails via [Anymail](https://github.com/anymail/django-anymail) (using [Mailgun](http://www.mailgun.com/) by default or Amazon SES if AWS is selected cloud provider, but switchable)
|
- Send emails via [Anymail](https://github.com/anymail/django-anymail) (using [Mailgun](http://www.mailgun.com/) by default or Amazon SES if AWS is selected cloud provider, but switchable)
|
||||||
- Media storage using Amazon S3, Google Cloud Storage or Azure Storage
|
- Media storage using Amazon S3, Google Cloud Storage, Azure Storage or nginx
|
||||||
- Docker support using [docker-compose](https://github.com/docker/compose) for development and production (using [Traefik](https://traefik.io/) with [LetsEncrypt](https://letsencrypt.org/) support)
|
- Docker support using [docker-compose](https://github.com/docker/compose) for development and production (using [Traefik](https://traefik.io/) with [LetsEncrypt](https://letsencrypt.org/) support)
|
||||||
- [Procfile](https://devcenter.heroku.com/articles/procfile) for deploying to Heroku
|
- [Procfile](https://devcenter.heroku.com/articles/procfile) for deploying to Heroku
|
||||||
- Instructions for deploying to [PythonAnywhere](https://www.pythonanywhere.com/)
|
- Instructions for deploying to [PythonAnywhere](https://www.pythonanywhere.com/)
|
||||||
|
|
|
@ -187,3 +187,7 @@ For status check, run::
|
||||||
|
|
||||||
supervisorctl status
|
supervisorctl status
|
||||||
|
|
||||||
|
Media files without cloud provider
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
If you chose no cloud provider and Docker, the media files will be served by an nginx service, from a ``production_django_media`` volume. Make sure to keep this around to avoid losing any media files.
|
||||||
|
|
|
@ -69,7 +69,7 @@ cloud_provider:
|
||||||
3. Azure_
|
3. Azure_
|
||||||
4. None
|
4. None
|
||||||
|
|
||||||
Note that if you choose no cloud provider, media files won't work.
|
If you choose no cloud provider and docker, the production stack will serve the media files via an nginx Docker service. Without Docker, the media files won't work.
|
||||||
|
|
||||||
mail_service:
|
mail_service:
|
||||||
Select an email service that Django-Anymail provides
|
Select an email service that Django-Anymail provides
|
||||||
|
|
|
@ -491,9 +491,12 @@ def main():
|
||||||
use_async=("{{ cookiecutter.use_async }}".lower() == "y"),
|
use_async=("{{ cookiecutter.use_async }}".lower() == "y"),
|
||||||
)
|
)
|
||||||
|
|
||||||
if "{{ cookiecutter.cloud_provider }}" == "None":
|
if (
|
||||||
|
"{{ cookiecutter.cloud_provider }}" == "None"
|
||||||
|
and "{{ cookiecutter.use_docker }}".lower() == "n"
|
||||||
|
):
|
||||||
print(
|
print(
|
||||||
WARNING + "You chose not to use a cloud provider, "
|
WARNING + "You chose to not use any cloud providers nor Docker, "
|
||||||
"media files won't be served in production." + TERMINATOR
|
"media files won't be served in production." + TERMINATOR
|
||||||
)
|
)
|
||||||
remove_storages_module()
|
remove_storages_module()
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
FROM nginx:1.17.8-alpine
|
||||||
|
COPY ./compose/production/nginx/default.conf /etc/nginx/conf.d/default.conf
|
|
@ -0,0 +1,7 @@
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
location /media/ {
|
||||||
|
alias /usr/share/nginx/media/;
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,6 +57,18 @@ http:
|
||||||
# https://docs.traefik.io/master/routing/routers/#certresolver
|
# https://docs.traefik.io/master/routing/routers/#certresolver
|
||||||
certResolver: letsencrypt
|
certResolver: letsencrypt
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
{%- if cookiecutter.cloud_provider == 'None' %}
|
||||||
|
|
||||||
|
web-media-router:
|
||||||
|
rule: "Host(`{{ cookiecutter.domain_name }}`) && PathPrefix(`/media/`)"
|
||||||
|
entryPoints:
|
||||||
|
- web-secure
|
||||||
|
middlewares:
|
||||||
|
- csrf
|
||||||
|
service: django-media
|
||||||
|
tls:
|
||||||
|
certResolver: letsencrypt
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
middlewares:
|
middlewares:
|
||||||
csrf:
|
csrf:
|
||||||
|
@ -77,6 +89,13 @@ http:
|
||||||
servers:
|
servers:
|
||||||
- url: http://flower:5555
|
- url: http://flower:5555
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
{%- if cookiecutter.cloud_provider == 'None' %}
|
||||||
|
|
||||||
|
django-media:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- url: http://nginx:80
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
# https://docs.traefik.io/master/providers/file/
|
# https://docs.traefik.io/master/providers/file/
|
||||||
|
|
|
@ -4,6 +4,9 @@ volumes:
|
||||||
production_postgres_data: {}
|
production_postgres_data: {}
|
||||||
production_postgres_data_backups: {}
|
production_postgres_data_backups: {}
|
||||||
production_traefik: {}
|
production_traefik: {}
|
||||||
|
{%- if cookiecutter.cloud_provider == 'None' %}
|
||||||
|
production_django_media: {}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
services:
|
services:
|
||||||
django:{% if cookiecutter.use_celery == 'y' %} &django{% endif %}
|
django:{% if cookiecutter.use_celery == 'y' %} &django{% endif %}
|
||||||
|
@ -24,6 +27,10 @@ services:
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
image: {{ cookiecutter.project_slug }}_production_django
|
image: {{ cookiecutter.project_slug }}_production_django
|
||||||
|
{%- if cookiecutter.cloud_provider == 'None' %}
|
||||||
|
volumes:
|
||||||
|
- production_django_media:/app/{{ cookiecutter.project_slug }}/media
|
||||||
|
{%- endif %}
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
- redis
|
- redis
|
||||||
|
@ -89,3 +96,14 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- production_postgres_data_backups:/backups:z
|
- production_postgres_data_backups:/backups:z
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
{%- if cookiecutter.cloud_provider == 'None' %}
|
||||||
|
nginx:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./compose/production/nginx/Dockerfile
|
||||||
|
image: {{ cookiecutter.project_slug }}_local_nginx
|
||||||
|
depends_on:
|
||||||
|
- django
|
||||||
|
volumes:
|
||||||
|
- production_django_media:/usr/share/nginx/media:ro
|
||||||
|
{%- endif %}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user