django + nginx on docker bad request (400) - django

I'm trying to get django (on gunicorn) and nginx running with docker. Unfortunately, I keep getting a Bad Request (400) error after I run docker-compose up -d --build. Help.
I have tried changing directories, directory names, volumes, networks and exposed ports to no avail. I also tried adding and removing server_name in my nginx.conf file.
In settings.py I have:
DEBUG = False
ALLOWED_HOSTS = ['127.0.0.1', 'localhost']
This is my docker-compose.yml file:
version: '3.3'
services:
web:
build: ./app
command: gunicorn my_server.wsgi:application --bind 0.0.0.0:8000
volumes:
- ./app/:/usr/src/app/
expose:
- 8000
environment:
- DATABASE=${DATABASE}
- SECRET_KEY=${SECRET}
- SQL_DATABASE=${POSTGRES_USER}
- SQL_ENGINE=django.db.backends.postgresql
- SQL_HOST=${POSTGRES_HOST}
- SQL_PASSWORD=${POSTGRES_PASSWORD}
- SQL_PORT=${POSTGRES_PORT}
- SQL_USER=${POSTGRES_USER}
- SU_NAME=${SU_NAME}
- SU_EMAIL=${SU_EMAIL}
- SU_PASSWORD=${SU_PASSWORD}
depends_on:
- db
logging:
driver: "json-file"
options:
max-size: "100k"
max-file: "20"
db:
image: postgres:11.2-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_USER=${POSTGRES_USER}
logging:
driver: "json-file"
options:
max-size: "100k"
max-file: "20"
nginx:
build: ./nginx
restart: unless-stopped
volumes:
- static_volume:/usr/src/app/assets
ports:
- 80:80
depends_on:
- web
logging:
driver: "json-file"
options:
max-size: "100k"
max-file: "20"
volumes:
static_volume:
postgres_data:
external: true
and this is my nginx.conf file:
upstream my_server {
server web:8000;
}
server {
listen 80;
location / {
proxy_pass http://my_server;
proxy_set_header Host $http_host;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
}
location /assets/ {
alias /usr/src/app/assets;
}
location /robots.txt {
alias /var/www/html/robots.txt;
}
}
In my Dockerfile for django, I run makemigrations and migrate and I have confirmed that the database tables are created.
I expect to go to localhost or 127.0.0.1 and see my website served there. Instead, I get this error: Bad Request (400).
When I run docker ps I get:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2dbc6ff7be78 my_server_nginx "nginx -g 'daemon of…" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp my_server_nginx_1
a6173e017c93 my_server_web "/usr/src/app/entryp…" 4 minutes ago Up 4 minutes 8000/tcp my_server_web_1
918e7bdae298 postgres:11.2-alpine "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 5432/tcp my_server_db_1
When I run docker logs my_server_nginx_1 I get lines like this:
172.18.0.1 - - [08/May/2019:22:25:07 +0000] "GET / HTTP/1.1" 400 37 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36" "-"
172.18.0.1 - - [08/May/2019:22:25:07 +0000] "GET /favicon.ico HTTP/1.1" 400 37 "http://localhost/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36" "-"

Probaly you need to add my_server to your allowed hosts(same as your upstream in NGINX config):
ALLOWED_HOSTS = ['my_server']

While trying to implement upinder kumar's solution I stumbled upon the solution. I will add here for anyone else facing this problem in the future:
The nginx.conf cannot have both
proxy_set_header Host $http_host;
and
proxy_set_header Host $host;
Deleting either one solved the problem.

Create socket file using gunicorn and configure in our virtual host.
#############Gunicorn configuration###################
[unit]
Description=gunicorn daemon
After=network.target
[Service]
User=root
Group=nginx
WorkingDirectory=/var/www/html/source
ExecStart=/var/www/html/env_source/bin/gunicorn --workers 3 --bind
unix:/var/www/html/source/source.sock application_name.wsgi:application
[Install]
WantedBy=multi-user.target
It will create file name source.sock just configure this sock file in nginx virtual host
###########nginx Configuratio
server {
server_name example.com;
listen 80;
access_log /var/www/html//source/access.log;
error_log /var/www/html/source/error.log;
include /etc/nginx/default.d/*.conf;
location /static/ {
root /var/www/html/source/run;
}
location / {
proxy_pass http://unix:/var/www/html/source/source.sock;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
}
}

if you define allowed hosts in settings.py:
ALLOWED_HOSTS = ['localhost','127.0.0.1','my_domain.com']
if you define allowed hosts in .env as an environment
variable, you should use the following format (without brackets):
in .env file:
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 my_domain.com
and in settings.py
ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "127.0.0.1").split()

Related

NGINX Docker reverse proxy not working on server (Works locally)

I am running a Django app on Docker with Nginx, the configuration works perfectly locally but on the server, it doesn't.
i get the error 502 Bad Gateway in the web page
and the logs I get
2023/01/13 07:55:56 [error] 28#28: *1 connect() failed (111: Connection refused) while connecting
to upstream, client: xx.xxx.xx.xxx, server: , request: "GET /favicon.ico HTTP/1.1", upstream:
"http://xxx.xx.x.x:8000/favicon.ico", host: "xx.xxx.xxx.xxx", referrer: "http://xx.xxx.xxx.xxx/"
This is how the configuration looks
Dockerfile
FROM nginx:1.23.3-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY ./default.conf /etc/nginx/conf.d/default.conf
default.conf
upstream apii {
server api:8000;
}
server {
client_max_body_size 20M;
listen 80;
location / {
proxy_pass http://apii;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
# location = /favicon.ico { access_log off; log_not_found off; }
location /api {
proxy_pass http://apii;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /realestateadmin {
proxy_pass http://apii;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /staticfiles/ {
alias /app/staticfiles/;
}
location /mediafiles/ {
alias /app/mediafiles/;
}
}
docker-compose.yml
version: "3.9"
services:
api:
build:
context: .
dockerfile: ./docker/local/django/Dockerfile
command: /start
volumes:
- .:/app
- static_volume:/app/staticfiles
- media_volume:/app/mediafiles
# ports:
# - "8000:8000"
expose:
- 8000
env_file:
- .env
depends_on:
- postgres-db
networks:
- real-estate
postgres-db:
image: postgres:12.0-alpine
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=${DB_NAME}
networks:
- real-estate
nginx:
restart: always
depends_on:
- api
volumes:
- static_volume:/app/staticfiles
- media_volume:/app/mediafiles
build:
context: ./docker/local/nginx
dockerfile: Dockerfile
ports:
- "80:80"
networks:
- real-estate
networks:
real-estate:
driver: bridge
volumes:
postgres_data:
static_volume:
media_volume:
I have tried different things. I doesn't make sense to me.

How to run django-channels + nginx + gunicorn + redis in docker?

I am trying run an django asgi app with nginx + gunicorn + redis in docker.so far my wsgi application is running by gunicorn smoothly but somehow my django channels consumers are not connecting.
Docker-Compose
version: '3.9'
services:
db:
image: postgres
volumes:
- ./data/db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=LiveSafer
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=demo1234
ports:
- "5432:5432"
web:
build: .
command: >
bash -c " python manage.py makemigrations &&
python manage.py migrate &&
gunicorn --bind 0.0.0.0:8000 LiveSafer.wsgi &&
daphne -b 0.0.0.0 -p 8001 LiveSafer.routing:application
"
volumes:
- .:/app
- static_files:/app/static
expose:
- 8000
ports:
- 8001:8001
links:
- redis
depends_on:
- db
nginx:
build: ./nginx/
ports:
- 80:80
volumes:
- ./nginx/conf.d/:/etc/nginx/conf.d/
- static_files:/home/app/static
depends_on:
- web
# database controller
adminer:
image: adminer:latest
restart: always
environment:
- ADMINER_DEFAULT_SERVER=db
- ADMINER_DESIGN=flat
- ADMINER_PLUGINS=tables-filter
ports:
- 8080:8080
redis:
image: redis:latest
command: ["redis-server", "--bind", "redis", "--port", "6379"]
volumes:
static_files:
db:
nginx
upstream django{
server web:8000;
}
upstream channels-backend {
server 127.0.0.1:8001;
}
server {
listen 80;
client_max_body_size 60M;
location / {
proxy_pass http://django;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header HOST $host;
}
location /ws/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_pass http://127.0.0.1:8001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location /media/ {
alias /app/media/;
}
location /static/ {
alias /home/app/static/;
}
}
Terminal
lifvesafer-nginx-1 | 2022/12/20 07:00:56 [error] 31#31: *10 connect() failed (113:
No route to host) while connecting to upstream, client: 172.19.0.1, server: , request:
"GET /favicon.ico HTTP/1.1", upstream: "http://172.19.0.5:8000/favicon.ico", host:
"127.0.0.1", referrer: "http://127.0.0.1/"
now i am not understanding why this is happening and how do i solve this

Nginx: Connection refused after removing port bindings from docker-compose file

Basically, I am trying to get access to MariaDB on the website. I needed to run a docker container so that it looks as if its network requests originate from the instance on which it runs (AWS Ubuntu Instance). For that, I used network_mode: "host" within my docker-compose file for each container. Also, I had to comment out the port bindings since they are not compatible with host network mode. However, now I get:
Connection refused error. I believe I have to change something within the nginx config file which is project.conf, but I am not sure what.
This is the docker-compose file:
version: '3'
services:
app:
restart: always
build: ./app
#ports:
# - "8501:8501"
env_file:
- .env
command: streamlit run Main.py
network_mode: "host"
mariadb:
image: mariadb:10.9.3
#ports:
# - "3306:3306"
volumes:
- db_data:/var/lib/mysql
- db_conf:/etc/mysql/conf.d
environment:
MYSQL_ROOT_PASSWORD: "xxx"
MYSQL_DATABASE: "xxx"
MYSQL_USER: "xxx"
MYSQL_PASSWORD: "xxx"
MYSQL_ROOT_HOST: "xxx"
network_mode: "host"
nginx:
restart: always
build: ./nginx
#ports:
# - "80:80"
depends_on:
- app
- mariadb
volumes:
db_data:
db_conf:
And, this is the project.conf file:
server {
listen 80;
server_name helloworld-st-app;
location / {
proxy_pass http://app:8501/;
}
location ^~ /static {
proxy_pass http://app:8501/static/;
}
location ^~ /healthz {
proxy_pass http://app:8501/healthz;
}
location ^~ /vendor {
proxy_pass http://app:8501/vendor;
}
location /stream {
proxy_pass http://app:8501/stream;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}
I tried removing 8501 from the url, still nothing. Any help on this would be much appreciated. Thanks in advance.

Nginx support multiple hostnames

I am working on my django + nginx + docker-compose project
I want to access my site via ip and mysite.com
Problem -- ip url is working, but mysite.com returns error:
403 Forbidden Nginx
My code - docker-compose.yml
services:
django:
build: ./project # path to Dockerfile
command: sh -c "
sleep 3 && gunicorn --bind 0.0.0.0:8000 core_app.wsgi"
...
expose:
- 8000
env_file:
- ./.env
depends_on:
- db
nginx:
image: nginx:1.19.8-alpine
depends_on:
- django
env_file:
- ./.env
ports:
- "80:80"
volumes:
- ./project/nginx-conf.d/:/etc/nginx/conf.d
...
nginx-conf.conf
upstream app {
server django:8000;
}
server {
listen 80;
server_name 127.0.0.1 mysite.com www.mysite.com;
location / {
proxy_pass http://django:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /var/www/html/static/;
}
}
UPDATE
I was trying to replace proxy_pass http://django:8000; with proxy_pass http://app; but it didn't help
Value of proxy_pass is incorrect.
When you're referencing an upstream group, you've to pass the name of the group to proxy_pass.
In your case, the name of upstream group is "app". So the value of proxy_pass should look like this:
proxy_pass http://app;

When I set DEBUG=False Django gives me 400 bad request am using [docker, nginx, django, gunicorn]

I am trying to define a production env for Django using docker and Nginx and Gunicorn and It works fine when debug=True If I make debug=False the Issue start here gives me Bad Request (400)
my Nginx file like this:
upstream API {
server backend-stack:8000;
}
server {
listen 80;
server_name localhost;
location / {
proxy_set_header Host $host;
proxy_pass http://api;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
}
location /static/ {
alias /backend/static/;
}
location /media/ {
alias /backend/media/;
}
}
my allowed_hosts In settings.py
if env.get("ALLOWED_HOSTS"):
ALLOWED_HOSTS = env.get("ALLOWED_HOSTS")
my gunicorn execute command from entrypoint.sh file:
gunicorn core.wsgi:application --bind 0.0.0.0:8000
also here Is my nginx container In docker-compose:
nginx:
container_name: nginx-stack
build: ./nginx
restart: always
volumes:
- ./nginx/config:/etc/nginx/conf.d
- ./nginx/log:/var/log/nginx
- static_volume:/app_backend/static
- media_volume:/app_backend/media
ports:
- 80:80
- 443:443
depends_on:
- backend
networks:
- app-network
my allowed_hosts value:
ALLOWED_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0', '*']
finaly access log file for nginx :
192.168.144.1 - - [12/Jun/2021:15:18:02 +0000] "GET / HTTP/1.1" 400 154 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36" "-"
ok, I did It the problem was happening because I don't create any view yet or any page with a URL after I create a new page and set it as the home page It's working now.