Dockerized Nginx and Django, how to serve static files - django

Im using Docker to containerize my Django environment, which looks like this (simplified a bit):
A Nginx (official image) docker container
An Ubuntu docker container with uwsgi and Django
The Nginx container are serving the uwsgi just fine, but I have not found a way to serve static files.
upstream proceed {
server proceed:8000;
}
server {
listen 80;
server_name mydomain.com;
location /static {
alias /srv/www/proceed/static/; # What to do here?
}
location / {
uwsgi_pass proceed;
include uwsgi_params;
}
}
Question: Whats the best way to serve static files from another container? A solution not involving volumes are preferable.

As said #larsks you need share volumes between containers.
Your django Dockerfile need to contains volume definitions
FROM ubuntu
....
VOLUME /srv/www/proceed/static # there is path to your static
When you run nginx container you need add volumes-from argument
docker run nginx --volumes-from django
And than you nginx config will works fine.
Note! path to static content into django container and into nginx container must be the same!

Related

How to hoste multiple Django websites on single sever using NGINX and uWSGI

i have a linux server running under Ubuntu server 20.04 LTS, i'm using NGINX as a web server and uWSGI as an application server, i have a Django website is already installed and running perfectly, and the exact way i did that is by following the instructions from this video https://www.youtube.com/watch?v=ZpR1W-NWnp4&t=2s, but the thing is that i have several websites that needs to be installed, so i tried to redo all of it for a second website on the same server, but that did not work at all.
My question is: once i install a Django project exactly the way shown in the video using Nginx and uWSGI, how to install another Django project in a practical manner, in other words how to install multiple Django projects using Nginx and uWSGI.
this is my nginx server block saved at /etc/nginx/sites-available/project_name.conf
# the upstream component nginx needs to connect to
upstream django {
server unix:///home/user/project_name/project_name.sock;
}
# configuration of the server
server {
listen 80;
server_name domain.com www.domain.com;
charset utf-8;
# max upload size
client_max_body_size 75M;
# Django media and static files
location /media {
alias /home/user/project_name/media;
}
location /static {
alias /home/user/project_name/static;
}
# Send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /home/user/project_name/uwsgi_params;
}
}
Try out this bash script I wrote. It set ups as many Django websites as you want with a simple command. The script installs all the dependencies on your server, creates a virtual environment for each site, and configures a database server and Gunicorn connector.

Nginx not finding static files in Dockered Django app in Azure Web App for containers

I managed to run my Django app locally with docker compose( Django container + Nginx container) and it works fine, but when i want to run it in Azure web app for containers nginx can't find the ressources.
I don't know if i should change some configuration so it can work in Azure services or i need to enable ports in azure app settings therefore my containers could communicate.
This is my nginx configuration (nginx.conf) :
upstream myapp {
server web:8000;
}
server {
listen 80;
server_name myappname.azurewebsites.net;
location / {
proxy_pass http://myapp;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /home/app/web/static/;
}
location /media/ {
alias /home/app/web/media/;
}
}
I don't know why it did work locally when i run docker compose but in azure web app nginx can't find static files.
Please let me know if I need to clarify or include anything else.
Thanks in advance.
Thank you Joseba S. . Posting your suggestion as an answer to help other community members.
python manage.py collectstatic
You need that command for Django to copy over all your static files to the directory specified in the STATIC_ROOT setting. Remember you have to execute that every time you have some change in your static files.
Spin down the development containers:
$ docker-compose down -v
Test:
$ docker-compose -f docker-compose.prod.yml up -d --build
$ docker-compose -f docker-compose.prod.yml exec web python manage.py migrate --noinput
$ docker-compose -f docker-compose.prod.yml exec web python manage.py collectstatic --no-input --clear
You can also verify in the logs via docker-compose -f docker-compose.prod.yml logs -f that requests to the static files are served up successfully via Nginx.
You can refer to Dockerizing Django with Postgres, Gunicorn, and Nginx, Cannot locate static files after deploying with docker and Nginx failing to serve django static or media files

Gunicorn does not show Django static files

I've seen this question asked before but none of the responses have helped.
I'm trying to deploy my Python3/Django project to AWS with gunicorn + nginx. The project name is vicver, and when I try to run
$ gunicorn --bind 0.0.0.0:8000 vicver.wsgi
I can see my site on the AWS public IP port 8000 but without any js/css or images. When I do the same with the runserver command it works fine.
My settings.py contains the following paths:
STATIC_ROOT = os.path.join(BASE_DIR,'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = [ os.path.join(BASE_DIR,'vicver/static') ]
And here's a screenshot of the terminal
https://imgur.com/a/KhgcXeT
It works when you run runserver command because you're in development mode. But when you want to deploy your application to production env, you should use some of these options to serve static files Deploying static files
Normally I use Nginx to serve static files, and create a reverse proxy to proxy other requests into the app which served by Gunicorn. You can take a look on this Deploying django application to serve your app by using Gunicorn too.
You can not serve your static and media file in the production mode(Debug=False). The best way to serve statics and media with this structure is by using Nginx.
First, you need to collect your statics using the following command:
python manage.py collectstatic
Then you need to edit your "nginx.conf" file using the following codes. Be careful to replace "/usr/src/app/" with your project path.
server {
listen 80 backlog=2048;
location = /favicon.ico { access_log off; log_not_found off;}
location /static/ {
alias /usr/src/app/vicver/static/;
}
location /media/ {
alias /usr/src/app/vicver/media/;
}
.
.
.
}

docker, nginx, django and how to serve static files

Goal: The set of docker containers for a production django website deployment.
My hang up in this process is that usually nginx directly serves the static files... Based on my understanding of a good architecture using docker, you would have a container for your wsgi server (probably gunicorn), a separate nginx container with an upstream server configuration pointing to your gunicorn container. The nginx container can load balance between multiple gunicorn containers.
But what this implies is that I have to install my django app's static files in the nginx container, which seems like bad practice since it's primary goal is really load balancing
Is it better to have three containers: nginx, gunicorn, and a dedicated static server (possibly nginx or lighthttpd) for static files?
With reference to serving static files, your options depend on the functionality of your application. There's a very nifty tool called dj-static which will help you serve static files by adding very minimal code.
The documentation is fairly simple and all you have to do is follow these steps.
I found this answer from Michael Hampton:
"This only works if the processes are in the same host, VM or container, because it tries to make a connection to the same machine. When they are in different containers, it does not work.
You need to alter your nginx configuration so that it uses the internal IP address of the uwsgi container." Link from the post
And definitely is something you have to keep in mind if you will have Nginx in a different container, also you have to set the nginx.conf, pointing your statics file directory as alias preventing a security issue.
I hope this code work for everybody, it took me a couple of ours to figure about how to compose Gunicorn, docker, and Nginx:
# nginx.conf
upstream djangoA {
server $DOCKER_CONTAINER_SERVICE:9000 max_fails=3 fail_timeout=0;
# In my case looks like: web:9000
}
Server {
include mime.types;
# The port your site will be served on
listen 80;
# the domain name it will serve for
server_name $YOUR_SERVER_NAME;# substitute your machine's IP address or FQDN
charset utf-8;
#Max upload size
client_max_body_size 512M; # adjust to taste
location /site_media {
alias $DIRECTORY_STATIC_FILES/site_media;#your Django project's media files have to be inside of the container have nginxs, you can copy them with volumes.
expires 30d;
}
location / {
try_files $uri #proxy_to_app;
}
# Finally, send all non-media requests to the Django server.
location #proxy_to_app {
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://djangoA;
}
}
And for the docker-compose:
#production.yml
version: '2'
services:
db:
extends:
file: base.yml
service: db
nginx:
image: nginx:latest
volumes:
- ./nginx:/etc/nginx/conf.d/
- ./$STATIC_FILE_ROOT/site_media:/$STATIC_FILE_ROOT/site_media
ports:
- "80:80"
depends_on:
- web
web:
extends:
file: base.yml
service: web
build:
args:
- DJANGO_ENV=production
command: bash -c "python manage.py collectstatic --noinput && chmod 775 -R project/site_media/static && gunicorn project.wsgi:application"
volumes:
- ./$DIRECTORY_APP:/$DIRECTORY_APP
ports:
- "9000:9000"
depends_on:
- db
volumes:
db_data:
external: true
If it's a django app using docker and/or kubernetes take a look at whitenoise http://whitenoise.evans.io/en/stable/ to provide a solution here.
This is a straightforward recommendation, but I spent much time searching around before I found it referenced.

Django + uwsgi + nginx redirect to default page "Welcome to NGINX"

I'm a very beginner in python and django. However I'm trying to create a server to deploy my application. But when I want to access my app, I always get the default nginx page "Welcome to nginx".
This server is on Ubuntu 12.04 (precise)
I've installed nginx, python, django and uwsgi packages with apt.
Next I've created a django project to /var/www/djangoApps and a django app to /var/www/djangoApps/testApp
This is my /etc/nginx/sites-available/djangoApps :
server {
listen 80
server_name django.pommesky.com;
rewrite ^(.*) http://www.django.pommesky.com/$1 permanent;
}
server {
listen 80;
server_name www.django.pommesky.com;
access_log /var/log/nginx/djangoApps_access.log;
error_log /var/log/nginx/djangoApps_error.log;
location /media {
alias /var/www/djangoApps/media/;
}
location /static {
alias /var/www/djangoApps/static/;
}
location / {
uwsgi_pass unix:///run/uwsgi/app/djangoApps/socket;
include uwsgi_params;
}
}
And this is my /etc/uwsgi/apps-available/djangoApps.ini :
env = DJANGO_SETTINGS_MODULE=djangoApps.settings
module = django.core.handlers.wsgi:WSGIHandler()
chdir = /var/www/djangoApps
socket = /run/uwsgi/djangoApps/socket
logto = /var/log/uwsgi/djangoApps.log
The uwsgi log doesn't show anything, everything seems to run well, it finishes by spawned uWSGI worker ...
But /var/log/nginx/djangoApps_access.log; and /var/log/nginx/djangoApps_error.log; don't exist, which is very strange.
I can't figure out what's wrong with my configuration.
Please help me ...
The domain django.pommesky.com doesn't look like it's alive, so it's possible that Nginx is receiving requests with wrong Host: field in the HTTP request header. (sect. 14.23) So Nginx serves a default catch-all page.
You can disable the default Nginx site by removing the /etc/nginx/sites-enabled/default link, and then restarting the daemon.
sudo rm -v /etc/nginx/sites-enabled/default
sudo service nginx restart
You can reenable by recreating the link:
sudo ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
sudo service nginx restart
The other thing you can try is to setup Bind or another DNS daemon to serve a fake pommesky.com zone with all the subdomains you want and use that DNS while you're developing your site.
Of course you can also register that domain with a hosting provider, and then use the DNS zone editor in its control panel to setup your subdomains and all the PTRs you want to whatever public IP addresses you need.