i have django back-end and reactjs front-end.
i want to load static files of django back-end with nginx but he can't find anything .
gunicorn can find django pages but can't load staticfiles
so i want nginx to serve django page and staticfiles.
this is my settings.py :
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, '/static')
docker-compose :
version: "3.9"
services:
backend:
build:
context: ./backend
ports:
- "8000:8000"
entrypoint: ./entrypoint.sh
# command: gunicorn server.wsgi:application --bind 0.0.0.0:8000
volumes:
- static:/static
nginx:
build:
context: .
dockerfile: ./webserver/Dockerfile
restart: always
ports:
- "80:80"
volumes:
- static:/static
depends_on:
- backend
volumes:
static:
and this is my default.conf :
upstream api {
server backend:8000;
}
server {
listen 80;
server_name myapp.loc;
root /usr/share/nginx/html/frontend1;
location / {
try_files $uri /index.html;
}
location /admin/ {
proxy_pass http://api;
}
location /static/ {
alias /static/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server {
listen 80;
server_name newapp.loc;
root /usr/share/nginx/html/frontend2;
location / {
try_files $uri /index.html;
}
location /admin/ {
proxy_pass http://api;
}
location /static/ {
alias /static/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
I think the problem occurs in the nginx config file.
location /static/ {
alias /static/;
}
Just now, it will alias to FRONTEND_ROOT/static/ (in this case, it is /usr/share/nginx/html/frontend1/static/), but what we expected is it should alias to BACKEND_ROOT/static/.
So the easiest way to solve this problem is to write absolute path here, to avoid alias to the frontend directory.
Create seperate entry in /etc/hosts for django.loc
Also make nginx configure for your back which will redirect you, changes in default.conf
server {
listen 80;
server_name django.loc;
location / {
proxy_pass http://localhost:8000/;
}
location /static/ {
alias /path/to/backend/static/;
} #OR YOU DONT NEED THIS, TELL BACKEND THAT ALLOW ACCESS TO STATIC
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Either specify complete path in static block, or else remove static path, and mention static directory in your framework.
Try this if not working let me know
Related
I was setting up basic Django site with nginx. When i navigate to the url of the file i get error 404 Not Found
nginx/1.18.0 (Ubuntu)
This is the conf file
upstream django {
server unix:///home/jo/testproject/testproject.sock;
}
# configuration of the server
server {
listen 80;
server_name _;
charset utf-8;
# max upload size
client_max_body_size 75M;
# Django media and static files
location /media/ {
alias /home/jo/testproject/media/;
}
location /static {
alias /home/jo/testproject/static;
}
# Send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /home/jo/testproject/uwsgi_params;
}
}
the media folder is in /home/jo/testproject/media and inside it i have media.gif, but ip/media/media.gif doesnt work
when i write the ip in the browser i get
Welcome to nginx!
If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.
Thank you for using nginx.
I think everything else i setup correctly
Docker + NGINX + Gunicorn + Django
Django project:
djangoapp
- ...
- media
- static
- manage.py
- requirements.txt
nginx
- Dockerfile
- nginx.conf
docker-compose.yml
Dockerfile
Dockerfile:
FROM ubuntu:20.04
# Prevents Python from writing pyc files to disc
ENV PYTHONDONTWRITEBYTECODE 1
# Prevents Python from buffering stdout and stderr
ENV PYTHONUNBUFFERED 1
ENV DEBUG 0
# https://hub.docker.com/r/fnndsc/ubuntu-python3/dockerfile
RUN apt-get update \
&& apt-get install -y python3-pip gunicorn
RUN mkdir /app
COPY djangoapp/requirements.txt requirements.txt
COPY djangoapp /app/
RUN pip3 install -r requirements.txt
WORKDIR /app/
EXPOSE 8000
CMD ["gunicorn3", "-b", "0.0.0.0:8000", "djangoapp.wsgi:application", "--workers=2"]
docker-compose.yml:
version: '3'
services:
djangoapp:
build: .
container_name: djangoapp1
volumes:
- .:/djangoapp
- static:/app/static
- media:/app/media
nginx:
build: ./nginx
container_name: nginx
environment:
- SERVER_NAME=8.43.162.54
ports:
- "80:80"
volumes:
- .:/djangoapp
- static:/app/static
- media:/app/media
restart: always
networks:
default:
driver: bridge
volumes:
media:
static:
nginx/Dockerfile:
FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
nginx/nginx.conf:
server {
listen 80;
server_name $SERVER_NAME;
location /static/ {
alias /app/static/;
}
location /media/ {
alias /app/media/;
}
location / {
proxy_set_header Host $host;
proxy_pass http://djangoapp1:8000;
}
}
settings.py:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = []
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
sudo nano /etc/nginx/sites-enabled/inventory.conf
the upstream component nginx needs to connect to
upstream django {
server unix:///home/user/Inventory-System/inventory.sock;
}
#configuration of the server
server {
listen 80;
server_name trading.code www.trading.code;
charset utf-8;
# max upload size
client_max_body_size 75M;
# Django media and static files
location /media {
autoindex on;
alias home/user/Inventory-System/media/;
}
location /static {
autoindex on;
alias home/user/Inventory-System/static/;
}
# Send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include home/user/Inventory-System/uwsgi_params;
} }
then
user#user: /etc/nginx/sites-enabled$ sudo rm default
user#user: $ sudo /etc/init.d/nginx restart
finally
check http://127.0.0.0/media/
I also faced this problem and I add this in my sudo nano /etc/nginx/sites-available/project file
server {
listen 80;
server_name 45.76.42.234;
location = /favicon.ico { access_log off; log_not_found off; }
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
location /static/ {
root /home/django/Django_tutorials/21_Django-deployment;
}
location /media/ {
root /home/django/Django_tutorials/21_Django-deployment;
}
location /Images/ {
alias /home/django/Django_tutorials/21_Django-deployment/Images/;
}
}
where Images is my image folder that contains uploaded images
I'm running my Django app in docker-compose and I'm exposing port 8000.
I have Nginx installed in the VM without docker and I want it to forward requets to my Django app, I tried to use host network in my docker-compose and create an external network but nothing worked and I'm always getting 502 Bad gateway
this my nginx.conf:
events {
worker_connections 4096; ## Default: 1024
}
http{
include /etc/nginx/conf.d/*.conf; #includes all files of file type.conf
server {
listen 80;
location /static/ {
autoindex on;
alias /var/lib/docker/volumes/app1_django-static;
}
location /media/ {
autoindex on;
alias /var/lib/docker/volumes/app1_django-media;
}
location / {
proxy_pass http://localhost:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
#For favicon
location /favicon.ico {
alias /code/assets/favicon.ico;
}
# Error pages
error_page 404 /404.html;
location = /404.html {
root /code/templates/;
}
}
}
and this is my docker-compose file:
version: "3.2"
services:
web:
network_mode: host
image: nggyapp/newsapp:1.0.2
restart: always
ports:
- "8000:8000"
volumes:
- type: volume
source: django-static
target: /code/static
- type: volume
source: django-media
target: /code/media
environment:
- "DEBUG_MODE=False"
- "DB_HOST=.."
- "DB_PORT=5432"
- "DB_NAME=db"
- "DB_USERNAME=.."
- "DB_PASSWORD=.."
volumes:
django-static:
django-media:
I was following this tutorial to create a backend and it worked.
I made simple a Django REST admin panel to upload images, it worked.
Then I created Vue frontend app, run npm run serve while in 'VScode remote' and it worked (images are fetched from Django and styled by Vue in my localhost).
The PROBLEM is it's not obvious how to make all this work in the production VPS server (i mean from Vue 'dist' folder after vue run build).
Everything I tried just gives me a 404 error or ruins the Django admin panel.
Here are my NGINX settings :
server {
server_name kruglovks.xyz www.kruglovks.xyz;
client_max_body_size 100m;
location = /favicon.ico { access_log off; log_not_found off; }
location /static {
root /home/kirill/myprojectdir/myproject;
}
location /media {
root /home/kirill/myprojectdir/myproject;
}
location /dist {
try_files $uri $uri/ /index.html;
alias /home/kirill/myprojectdir/myproject;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
Vue router is set to history mode.
Please, I need some info on how to make Vue work in this configuration.
P.S. Maybe there is an alternative way of using Vue alongside Django?
Thank you so much and have a nice day!
That was a huge step forward, not a 404 but blank page called 'frontend' and browser refused to find css and js.
Later with a friends help and thisguide i could reconfigure nginx settings to this :
server {
listen 80;
server_name kruglovks.xyz www.kruglovks.xyz;
root /home/sasha/myprojectdir/myproject/dist/;
client_max_body_size 100m;
location = /favicon.ico { access_log off; log_not_found off; }
location /static {
alias /home/sasha/myprojectdir/myproject/static;
}
location /media {
alias /home/sasha/myprojectdir/myproject/media;
}
location / {
try_files $uri $uri/ /index.html;
}
location ^~ /api/ {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
location ^~ /admin {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
and it works now !
Thank you so muck #Danizavtz, you saved me like weeks of life ...
You are not listening to any ports.
Notice that in location /dist you also have to change the order of operations
Try to change your default to this configuration:
server {
listen 80;
server_name kruglovks.xyz www.kruglovks.xyz;
root /var/www;
#... configurations
location /dist {
alias /home/kirill/myprojectdir/myproject;
try_files $uri $uri/ /index.html;
}
And the vuejs application will be served in www.kruglovks.xyz/dist.
This is for production, not intended for development environment. Django application deployed using Guncorn
# settings.py
ALLOWED_HOSTS=['yourdomain.com', 'localhost'] # 'localhost' is optional
...
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
If using 'corsheaders' then add yourdomain.com
# settings.py
CORS_ALLOWED_ORIGINS = `[`
"https://yourdomain.com",
"http://yourdomain.com", # Use this if SSL in not configured
"http://localhost"
]
Update 'urls.py' for the project, and choose path for your application; mine is 'app/api/' so it will direct to http://yourdomain.com/app/api/
urlpatterns = [
path('app/api/', include('api.urls')),
path('app/admin/', admin.site.urls),
]
NGINX Configurations
# /etc/nginx/sites-available/yourdomain.com.conf
server {
root /var/www/app/dist; # Vue app production build
index index.html index.htm index.nginx.debian.html;
server_name yourdomain.com www.yourdomain.com;
# Django folder
location /static/ {
root /path/to/django/project/folder;
}
# Django web requests handled here
location /app/ {
# Gunicorn and other configurations
...
}
# Everything else handled by Vue
location / {
try_files /$uri /$uri/ /index.html$args;
}
...
}
You can also use Nginx to serve Vue and another Nginx instance to work as reverse proxy to serve Django statics (Gunicorn will serve Django dynamic content i.e API calls/ responses) - you will get faster serving of static content and improved security layer on the way.
Here is why tu use Nginx -> https://djangoadventures.com/what-is-the-point-of-using-nginx-in-front-of-a-django-application/
Nice example here for Docker, Django, Postres, Nginx -> https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/
For Vue - Nginx can also serve that. Remember to edit settings.py with Cors and allowed hosts.
If you want incorporate nginx proxy to the frontend then you can do that by 2 separate nginx files like:
frontend file -> nginx.conf
server {
listen 8080;
location / {
root /code;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
backend file -> default.conf
upstream backend {
server backend:8000;
}
upstream frontend {
server frontend:8080;
}
server {
listen 80;
root /usr/share/nginx/html;
include /etc/nginx/mime.types;
# Vue frontend.
location / {
proxy_pass http://frontend;
}
# Django API.
location /api {
proxy_pass http://backend;
autoindex off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
# Django static assests.
location /static/ {
autoindex on;
alias /code/staticfiles/;
}
}
Dockerfile for Django
# Build from minimal image for speed and security
FROM python:3.10.2-slim-bullseye
ENV WORKDIR=/code
ENV USER=code
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR $WORKDIR
COPY requirements.txt $WORKDIR
# make static files dirs in order to avoid error from collectstatic
RUN mkdir $WORKDIR/staticfiles && \
mkdir $WORKDIR/staticfiles/admin && \
mkdir $WORKDIR/staticfiles/rest_framework
RUN pip install --upgrade pip && \
pip install -r requirements.txt && \
adduser --system --group $USER && \
chown -R $USER:$USER $WORKDIR
COPY ./app/backend $WORKDIR
USER $USER
EXPOSE 8000
Dockerfile for vue
FROM node:lts-alpine as build-stage
ENV WORKDIR=/code
WORKDIR $WORKDIR
# copy both 'package.json' and 'package-lock.json' (if available) from you project dir
COPY app/frontend/package*.json $WORKDIR/
# install project dependencies
RUN npm install --legacy-peer-deps
COPY app/frontend $WORKDIR
RUN npm run build
# Serve Vue
FROM nginx:alpine as production-stage
RUN mkdir $WORKDIR
COPY app/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build-stage $WORKDIR/dist $WORKDIR
EXPOSE 8080
Then Docker compose
version: "3.5"
volumes:
postgres_data:
static_volume:
services:
backend:
container_name: django_backend
env_file:
- .env
build:
context: .
dockerfile: Dockerfile.django
restart: unless-stopped
# Should go into separate *.sh file but for simplicity - you starting Gunicorn to serve Django
command: >
sh -c "python manage.py wait_for_db &&
python manage.py migrate --noinput &&
python manage.py collectstatic --no-input &&
gunicorn your_project.wsgi:application --bind 0.0.0.0:8000"
volumes:
- static_volume:/code/staticfiles
depends_on:
- database
frontend:
container_name: vue_frontend
build:
context: .
dockerfile: Dockerfile.vue
restart: unless-stopped
nginx:
container_name: nginx_proxy_server
build:
context: .
dockerfile: Dockerfile.nginx_proxy
restart: unless-stopped
ports:
- 80:80
volumes:
- static_volume:/code/staticfiles
depends_on:
- frontend
- backend
database:
container_name: postgres_db
build:
context: .
dockerfile: Dockerfile.postgres
volumes:
- postgres_data:/var/lib/postgresql/data/
# from .env
environment:
- POSTGRES_HOST=${DATABASE_HOST}
- POSTGRES_USER=${DATABASE_USER}
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
- POSTGRES_DB=${DATABASE_NAME}
I am struggling with the connection of nginx and django (docker container)
My strategy is like this ,
run uwsgi http option and 8001 port. (not socket)
uwsgi --http :8001 --module myapp.wsgi --py-autoreload 1 --logto /tmp/mylog.log
then I confirmed wget http://127.0.0.1:8001 works.
but from, nginx, It can't connect somehow. (111: Connection refused) error
However from nginx wget http://django:8001 works.
How can I connect between containars
upstream django {
ip_hash;
server 127.0.0.1:8001;
}
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location /static {
alias /static;
}
location / {
proxy_pass http://127.0.0.1:8001/;
include /etc/nginx/uwsgi_params;
}
}
server_tokens off;
I am trying this config but, if I try this, my container doesn't launch.
log is like this
2020/03/24 08:24:04 [emerg] 1#1: upstream "django" may not have port 8001 in /etc/nginx/conf.d/app_nginx.conf:16
upstream django {
ip_hash;
server django:8001;
}
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location /static {
alias /static;
}
location / {
proxy_pass http://django:8001/;
include /etc/nginx/uwsgi_params;
}
}
server_tokens off;
my docker compose is very simple...
nginx:
image: nginx:1.13
container_name: nginx
ports:
- "8000:8000"
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./nginx/static:/static
depends_on:
- django
Finally thanks to helps. my server works. final conf is like this below.
remove upstream and use name 'django' instead of 127.0.0.1
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location /static {
alias /static;
}
location / {
proxy_pass http://django:8001/;
include /etc/nginx/uwsgi_params;
}
}
server_tokens off;
If they run in different containers, 127.0.0.1 is not the correct IP; use the name of the other container, e.g.
proxy_pass http://django:8001;
so Docker's internal DNS can route things.
I try to put build of react app on localhost/ using nginx. As far as i understand this, i need to build app with "npm run build" and then serve build dir with static content. After many hours i managed to get it into work with docker and my django service as a api under localhost/api/. But what is not working is css and js on this sites. On any page neither is it react or django endpoints there is only raw html with attached css but not working. After many attempts with changing configs etc. I ended with same raw html. Why on nginx there is no styling on sites even if with inspecting these pages there is linked css to them.
This is my nginx.conf
http {
server {
listen 80;
listen [::]:80;
root /var/www/html;
server_name localhost;
index index.html index.htm;
location /api/ {
proxy_pass "http://web:8000/";
}
location / {
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
root /var/www/html;
expires 1M;
access_log off;
add_header Cache-Control "public";
}
}
}
This is part of docker-compose
nginx:
image: nginx:latest
ports:
- 80:80
- 443:443
volumes:
- ./nginx_conf/:/etc/nginx/
- ./frontend/build/:/var/www/html/
depends_on:
- web
When i run this app with npm start : image
When i enter localhost/ with nginx running : image
Ok i don't understand why. But i was messing with inspector and i clicked by accident disable http cache AND bootstrap loaded!? I really have no idea how but now it works.
i add 2 include into server and it's worked:
include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;