cookiecutter-django
cookiecutter-django copied to clipboard
Serving media files without an external service
Description
Currently, in order to serve media files, you need an external file storage service. Setting up an external file storage service introduces some complexity (especially for people who do not already use these services), as well as potentially extra costs. Even though it is a proper way to serve files in production, I believe it is not a requirement for all the use-cases that, in my opinion, are within the scope of cookiecutter-django. Deployment of small-scale projects could benefit by a simpler configuration.
Proposition
I propose to have an option to serve media files without an external service.
We are using Traefik as a reverse proxy. Traefik does not serve files (by design) therefore a web server is needed to do this job. To achieve this, we can have an Nginx behind Traefik to handle the media files route only.
Comments
- The trade-off is that we add yet another docker resource in the project, making it the complete system bigger (maintenance, resources, build time etc.)
- Nginx is a beast of its own
- Someone might argue why not use Nginx exclusively (why use Traefik); that was the state previously but the project switched to Caddy and later to Traefik, and part of the reason was because it is easier and safer to get automatic SSL certificates
- I am currently testing this setup with a small project and so far seems OK.
Closing
Would the maintainers be interested to add this? Are there any major disadvantages that I am missing?
Hello how about just setting up whitenoise to serve your files? Its more simpler as compared to coming up with an inbuilt configuration.
Are we talking about static files or media files? These are 2 different things, static files are part of your code while media files are more the one that are created in the lifetime of your app (user uploaded content, generated PDF, etc...). Whitenoise is not suitable for media files.
@Labohkip81 exactly what browniebroke said. Further, cookiecutter-django already provides the option to use whitenoise to serve static files.
@browniebroke I am talking about media files.
I own a very small website where I opted to use nginx to serve the media files. The additional configuration is not very hard to set up. It's like 10 lines in the docker compose and another 10 for the nginx config.
I went ahead and tried to implement an example of how this can be integrated. The way I use Traefik differs from the repo style so I adapted my approach to better suit this codebase. Hopefully this can be used as a starting point to see whether adding this feature or even expanding it is feasible.
I'm running into this same problem now. Trying to deploy a production instance for a university project, and not trying to deal with CDN for the setup we have.
Tried @ArkadiuszMichalRys's fork, but getting several errors: https://github.com/pydanny/cookiecutter-django/pull/2457#issuecomment-597281545
I have updated the pull request to include a few fixes. The generated project now works when I test it. You will want to choose option 3 (nginx) for the cloud provider and enable whitenoise.
I am not sure about a use case where nginx would be used without whitenoise but I left the option in there in case I am missing something.
Can the existing AWS S3 be configure to work with minio?
I applied the pull request manually.
It works, but the development server reloads when it detects uploaded files.
I don't see a way to exclude a directory: https://www.uvicorn.org/settings/
@OmarWKH the method I describe in this issue is for production only. In development, files are served by the development server; you don't need to use NGINX.
@demestav You are right. The problem I mentioned isn't related to this thread (if it's a problem at all).
I would like to add. Even from a not so small setup, you still want to choose to serve static and media files from an NGINX or Apache HTTPd and not using Whitenoise or an external service.
Also the creators of Whitenoise said it themselves:
"What’s the point in WhiteNoise when I can do the same thing in a few lines of Apache/nginx config? There are two answers here. One is that WhiteNoise is designed to work in situations were Apache, nginx and the like aren’t easily available."
Cookiecutter does not take this situation into account when there is an Apache HTTPd or NGINX server available.
Hi @demestav
Thanks for this question. It has been on my mind recently since I am running a service that needs to talk to a local media folder. I am using Nginx exclusively with no Traefik. Any indicators on how you set up your implementation?
@Afrowave
The nginx configuration part you are looking for might be this:
server {
listen 80;
server_name localhost;
location /media/ {
alias /usr/share/nginx/media/;
}
}
Thanks @arrys,
I managed to build this set up successfully. I am using Docker.
I added:
- I created
compose/nginx/conf.d/default.confand aded: - In
config/settings/production, I confirmed the location to myMEDIA_ROOT.
location ^~ /media/ {
autoindex on;
include /etc/nginx/mime.types;
alias /app/media/;
}
mediatovolumesand annginxblock toservicesin the `production.yml.
For further reading you can check out Serve Django Media Files via Nginx on stackoverflow
Once I get some time and people ask for it, I will create a PR for this.
@Afrowave sorry for the late reply to your earlier post. It's been a year since I did this, but I think it is pretty much what you described above, that is, to add NGINX as a new service in compose, create a media volume where the Django media directory is mounted on and serve that directory from NGINX.
However, as I said earlier, I believe it is best to hear from the maintainers of this project about this proposition, since adding a new container on the production environment might not fit well with the project's mission.
@Afrowave I have created a similar pull request (#2457) as a proof of concept a year ago. Some of my projects have been using a modified version since so I can attest to this being a viable solution for some people.
I think @demestev put my other thoughts into words in his previous comment. It is up to the maintainer to decide if the option fits the project.
Thanks @arrys,
I had a look at #2449 and #2457. Your PR has some conflicts with Traefik so it is true that this is up to the maintainers.
I have never implemented the Traefik version since I was and am comfortable with Nginx. This is yet another reason I will probably not look at Traefik soon.