Django Nginx Docker Gunicorn cant reach - django

Sorry if it the answer seems obvious, but I've been bashing my head for the past couple of hours.
I've been following multiple tutorials trying to dockerize my application. No matter what combination of url:port or just url I tried I can't access the pages.
I have zero clue what am I doing wrong. I am assuming the following:
NGINX config plain wrong. How can upstream web know what's web? I assume docker exposes it, but unsure whether this is correct.
web container not exposing address and port properly?
I tried multipled settings, but non work.
I have the following:
Dockerfile
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
ADD ./django.conf /etc/nginx/conf.d/default.conf
#COPY ./django.conf /etc/nginx/sites-available/
#RUN ln -s /etc/nginx/sites-available/django.conf /etc/nginx/sites-enabled
docker-compose.yml
version: '3'
services:
db:
image: postgres:9.6
ports:
- "5432:5432"
environment:
- POSTGRES_USER=random_user
- POSTGRES_PASSWORD=random_password
redis:
restart: always
image: redis:4.0
expose:
- "6379"
nginx:
image: nginx:1.14.0
container_name: nginx01
ports:
- "8000:8000"
volumes:
- ./code
depends_on:
- web
web:
build: .
container_name: backend-api
command: bash -c "python manage.py migrate && python manage.py collectstatic --noinput && gunicorn ops4_backend.wsgi -b 0.0.0.0:8000"
depends_on:
- db
volumes:
- ./code
expose:
- "8000"
restart: always
django.conf
upstream web {
ip_hash;
server web:8000;
}
# portal
server {
location / {
proxy_pass http://web:8000;
}
listen 8000;
server_name localhost;
location /static {
autoindex on;
alias /src/static/;
}
}
docker ps -a

I was doing almost the same task yesterday, and the only valuable difference I see is that you include django.conf in Django container, not in nginx one. I have following volume in nginx section of docker-compose.yml:
- ./nginx:/etc/nginx/conf.d (where ./nginx is the folder with django.conf)
EDIT: here is my docker-compose.yml:
version: '3'
services:
nginx:
image: nginx
restart: always
ports:
- "80:8000"
volumes:
- ./nginx:/etc/nginx/conf.d
- ./static_cdn:/static
depends_on:
- web
db:
image: postgres
restart: always
web:
build: .
restart: always
command: bash -c "python3 manage.py makemigrations && python3 manage.py migrate && python3 manage.py collectstatic --no-input && gunicorn core.wsgi -b 0.0.0.0:8000"
volumes:
- .:/code
expose:
- "8000"
depends_on:
- db
django.conf:
upstream web {
ip_hash;
server web:8000;
}
server {
location /static/ {
alias /static/;
}
location / {
proxy_pass http://web/;
}
listen 8000;
server_name localhost;
}
With this setup nginx is available at 127.0.0.1:80 or just 127.0.0.1 as 80 is default http port.

There are so many wrong things, please use this configuration. and then change it step by step toward your specific needs.
also checkout this page that talks about Nginx Docker Configurations because one of your main problems is that you are not exposing django nginx conf that you make:
ADD ./django.conf /etc/nginx/conf.d/default.conf
to nginx container.
so nginx does not know how to map your configs.

Related

Unable to deploy Django/Docker/Nginx/Gunicorn/Celery/RabbitMQ/SSL on AWS Lightsail

I have been trying for more than a week few hours daily.
Needless to say, I'm beginner in most of these things, but I have tried hundreds of configurations and nothing worked.
That's why I am finally coming here for help.
I am currently getting 502 Bad Gateway.
My suspicion is that either Nginx can't find staticfiles (if that's a reason for a 50x error) or nginx upstream doesn't know what is web (in config), or something with permissions on nginx.
Nginx error logs are printing this:
connect() failed (111: Connection refused) while connecting to upstream...upstream: "https://some-ip-address-here?:443" (this might be that nginx doesn't know about the web)
Dockerfile
# Pull base image
FROM python:3.10.2-slim-bullseye
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Create and set work directory called `app`
RUN mkdir -p /app
RUN mkdir -p /app/staticfiles
WORKDIR /app
# Install dependencies
COPY requirements.txt /tmp/requirements.txt
RUN set -ex && \
pip install --upgrade pip && \
pip install -r /tmp/requirements.txt && \
apt-get -y update && \
apt-get -y upgrade && \
apt-get install -y ffmpeg && \
rm -rf /root/.cache/
# Copy local project
COPY . /app/
COPY wait-for-it.sh /wait-for-it.sh
RUN chmod +x /wait-for-it.sh
docker-compose.yml
version: '3.7'
services:
web:
container_name: web
build: .
restart: always
command: ["/wait-for-it.sh", "db:5432", "--", "gunicorn", "--bind", "0.0.0.0:8000", "--workers", "3", "my_project.wsgi"]
volumes:
- .:/app
ports:
- "8000:8000"
- "443"
env_file: .env
depends_on:
- db
nginx:
container_name: nginx
restart: always
image: jonasal/nginx-certbot:4.2.0-nginx1.23.3
env_file:
- .env.nginx
volumes:
- nginx_secrets:/etc/letsencrypt
- ./nginx/user_conf.d:/etc/nginx/user_conf.d
- .:/app
ports:
- 80:80
- 443:443
depends_on:
- web
- db
db:
container_name: db
image: postgres:13
restart: always
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file: .env
celery:
container_name: celery
restart: always
build:
context: .
command: celery -A my_project worker -l info -B
volumes:
- .:/app
env_file:
- .env
depends_on:
- web
- rabbitmq3
rabbitmq3:
container_name: rabbitmq
image: rabbitmq:3-management-alpine
ports:
- 5672:5672
- 15672:15672
volumes:
postgres_data:
nginx_secrets:
Nginx config
upstream web {
server web:443;
}
# Redirect all HTTP requests to HTTPS
server {
listen 80;
server_name myurl.com;
return 301 https://$server_name$request_uri;
location /static/ {
alias /app/staticfiles/;
}
location /media/ {
alias /app/media/;
}
}
# Pass request to the web container
server {
location / {
proxy_pass https://web/;
}
access_log /var/log/nginx/project.access.log;
error_log /var/log/nginx/project.error.log;
# Listen to port 443 on both IPv4 and IPv6.
listen 443 ssl default_server reuseport;
listen [::]:443 ssl default_server reuseport;
server_name www.myurl.com myurl.com;
# Load the certificate files
ssl_certificate /etc/letsencrypt/live/my-site/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my-site/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/my-site/chain.pem;
# Load the Diffie-Hellman parameter
ssl_dhparam /etc/letsencrypt/dhparams/dhparam.pem;
location /static/ {
alias /app/staticfiles/;
}
location /media/ {
alias /app/media/;
}
}

Nginx frontend not calling Nginx in backend

So I am using Django + react with nginx both on backend and frontend, containerized in docker. The following image will clarify how I want to serve the whole application:
Having been googling but couldn't make sense of the solutions. Issue is that Nginx in frontend not connecting with nginx on backend on port 8082.
Following are docker, nginx and docker-compose files.
Nginx configurations for frontend:
upstream react {
server reactapp:3000;
}
server {
listen 80;
client_max_body_size 100M;
proxy_set_header X-Forwarded-Proto $scheme;
location / {
root /usr/share/nginx/html;
}
location /add-to-waiting/ {
proxy_pass http://0.0.0.0:8082;
}
}
Dockerfile for react and nginx for frontend:
# build environment
FROM node as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm i --silent
RUN npm install react-scripts#3.4.1 -g --silent
COPY . ./
RUN npm run build
# production environment
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]
docker-compose.yml for frontend:
services:
frontend:
build: .
ports:
- "8090:80"
container_name: irisfrontend
Nginx configurations for backend
upstream django {
server website:8000;
}
server {
listen 80;
client_max_body_size 100M;
proxy_set_header X-Forwarded-Proto $scheme;
location / {
proxy_pass http://django;
}
location /media/ {
alias /app/media/;
}
location /static/ {
alias /app/forex/static/admin/;
}
}
Dockerfile for nginx in backend:
FROM nginx:1.19.0
COPY ./default.conf /etc/nginx/conf.d/default.conf
Dockerfile for gunicorn in backend:
FROM python:3
ADD requirements.txt /app/requirements.txt
ADD . /app
WORKDIR /app
EXPOSE 8000:8000
RUN pip install --upgrade pip && pip install -r /app/requirements.txt
RUN python manage.py collectstatic --no-input --settings=forex.settings.production
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "3", "forex.wsgi:application", "DJANGO_SETTINGS_MODULE=forex.settings.production"]
docker-compose.yml for backend:
services:
db:
build: ./db
website:
build:
context: .
dockerfile: Dockerfile.app
env_file:
- env
container_name: website_container_8
volumes:
- static:/app/forex/static/admin/
depends_on:
- db
nginx:
build: ./nginx
volumes:
- static:/app/forex/static/admin/
ports:
- "8082:80"
depends_on:
- website
volumes:
static:
What changes do I need to make to successfully do a post request from frontend nginx to backend nginx?
Include a network for both containers so that they can communicate.
services:
db:
build: ./db
website:
build:
context: .
dockerfile: Dockerfile.app
env_file:
- env
container_name: website_container_8
volumes:
-
static:/app/forex/static/admin/
depends_on:
- db
networks:
- nettest
nginx:
build: ./nginx
volumes:
-
static:/app/forex/static/admin/
ports:
- "8082:80"
depends_on:
- website
networks:
- nettest
volumes:
static:
networks:
nettest:

Static files are not served but accessible directly. Django, docker, nginx

I am trying to dockerize a django project with postgres, gunicorn and nginx. My problem is that static files are not served. However in browser console I see all static files being loaded properly (code 200). Also I can easily access any static file directly i.e. 127.0.0.1:8080/static/admin/.../base.css. Nginx doesn't show any errors in console either. What makes it even more strange for me, my redoc.yaml is loaded properly.
Here is part of my settings.py with static:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
Here is my main Dockerfile:
FROM python:latest
RUN mkdir /code
COPY requirements.txt /code
RUN pip install -r /code/requirements.txt
COPY . /code
WORKDIR /code
CMD gunicorn api_yamdb.wsgi:application --bind 0.0.0.0:8000
Here is the Dockerfile for nginx:
FROM nginx:latest
COPY nginx/nginx.conf /etc/nginx/nginx.conf
Here is the nginx.conf file:
events {}
http {
server {
location /static/ {
root /etc/nginx/html/;
}
location / {
proxy_pass http://web:8000;
}
}
}
And finally here is my docker-compose:
version: '3.8'
volumes:
postgres_data:
static:
services:
db:
image: postgres:latest
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./.env
web:
build: .
restart: always
command: gunicorn api_yamdb.wsgi:application --bind 0.0.0.0:8000
volumes:
- static:/static
ports:
- "8000:8000"
depends_on:
- db
env_file:
- ./.env
nginx:
build:
context: .
dockerfile: nginx/Dockerfile
ports:
- "8080:80"
volumes:
- ./static:/etc/nginx/html/static
Any help is welcome. Thank you.
This can be fixed by adding include mime.types; into http section of nginx.conf

Nginx redirects to https://web

My webapp was working fine until today, when my domain stopped working. I was using example.com:8000/ to reach my Django app, but now it redirects me to https://web/. I've tried to go back to previous commits, but the issue does not disappear.
My nginx.conf looks like:
upstream web {
ip_hash;
server web:8000;
}
# portal
server {
location /static/ {
autoindex on;
alias /static/;
}
location / {
proxy_pass http://web/;
}
listen 8000;
server_name localhost;
}
docker-compose.yaml looks like:
version: '3'
services:
nginx:
image: nginx:latest
container_name: ng01
ports:
- "8000:8000"
volumes:
- ./code:/code
- ./code/nginx:/etc/nginx/conf.d
- ./static:/static
depends_on:
- web
web:
build: .
container_name: dg01
command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn fortex.wsgi -b 0.0.0.0:8000"
volumes:
- .:/code
- ./static:/static
expose:
- "8000"
depends_on:
- db
db:
image: postgres
container_name: ps01
volumes:
- pg_volume:/var/lib/postgresql/data
volumes:
pg_volume: {}
Nginx redirects without logging, but when I use incognito in chrome it logs normally but still redirects me.

docker ERROR: for nginx Cannot start service nginx: driver failed programming external connectivity on

I'm new to Docker and setting up my first Django application using Docker
My application path looks like
app
|- helloworld
|- __init__.py
|- manage.py
|- static_cdn
|- static_root
|- config
|- nginx
|- nginx.conf
|- Dockerfile
|- docker-compose.yml
|- requirements.txt
|- start.sh
the contents of Docerfile
FROM ubuntu:18.04
# -- Install Pipenv:
FROM python:3
ENV PYTHONUNBUFFERED 1
ENV LC_ALL C.UTF-8
ENV LANG C.UTF-8
# -- Install Application into container:
RUN set -ex && mkdir /app
WORKDIR /app
ADD requirements.txt /app/
RUN pip install -r requirements.txt
# -- Adding dependencies:
ADD . /app/
contents of docker-compose.yml
version: '3'
services:
nginx:
image: nginx:latest
ports:
- "9010:9010"
volumes:
- .:/app
- ./config/nginx:/etc/nginx/conf.d
- ./static_cdn:/static
depends_on:
- web
web:
build: .
command: ./start.sh
volumes:
- .:/app
- ./static_cdn:/static
ports:
- "9010:9010"
depends_on:
- db
expose:
- "9010"
db:
image: postgres
contents of config/nginx/nginx.conf
upstream web {
ip_hash;
server web:9010;
}
server {
location /static {
autoindex on;
alias /static/
}
location / {
proxy_pass http://127.0.0.1;
}
listen 9011;
server_name localhost;
}
contents of start.sh
#!/usr/bin/env bash
# Start Gunicorn processes
echo --: Starting application build
echo --: Creating migration
exec python3 manage.py makemigrations
echo ------: makemigrations complete
echo --: Running migration
exec python3 manage.py migrate
echo ------: migrate complete
echo --: Running collectstatic
exec python3 manage.py collectstatic
echo ------: collectstatic complete
echo Starting Gunicorn.
exec gunicorn helloworld.wsgi:application \
--bind 0.0.0.0:9010 \
--workers 3
Now, when I build using docker
docker-compose up --build
It gives error as
ERROR: for nginx Cannot start service nginx: driver failed
programming external connectivity on endpoint koober_nginx_1
(8ea5c084a7283a16afbf136a73dc4b27d9cae35fe14d735b83199ad5d0e03431):
Bind for 0.0.0.0:9010 failed: port is already allocated
I have followed few tutorials to create those Docker files and nginx conf file.
1. How can I solve above issue.
2. Do I need to use FROM ubuntu:18.04 with above configuration?
Edit 2
Now, it stuck after creating migration from start.sh commands
You can't allocate port 9010 of your host for both services.
This is what you're doing in the ports section of declaration of service nginx and web.
Moreover, by default nginx will listen to port 80 and 443 for https.
You can keep it like that and publish to a different port on your host. See how to use port keyword in docker-compose :
https://docs.docker.com/compose/compose-file/#ports
Maybe you want something more like that:
version: '3'
services:
nginx:
image: nginx:latest
ports:
- "10080:80"
- "10443:443"
volumes:
- .:/app
- ./config/nginx:/etc/nginx/conf.d
- ./static_cdn:/static
depends_on:
- web
web:
build: .
command: ./start.sh
container_name: "web-app"
volumes:
- .:/app
- ./static_cdn:/static
expose:
- "9010"
depends_on:
- db
db:
image: postgres
contents of config/nginx/nginx.conf
upstream web {
ip_hash;
server web-app:9010;
}
server {
location /static {
autoindex on;
alias /static/
}
location / {
proxy_pass http://web;
}
listen 80;
server_name localhost;
}
Concerning your last question, you could go for an official Python image from the Docker hub Python repository or start from any other base image like debian:jessie-slim from Debian official repository or keep the Ubuntu 18.04 image
For me, stopping/restarting the NGINX server worked.
To stop Nginx, use the following command:
sudo systemctl stop nginx
To start Nginx when it is stopped, use the following command:
sudo systemctl start nginx
To restart Nginx, use the following command:
sudo systemctl restart nginx
To reload Nginx after making configuration changes, use the following command:
sudo systemctl reload nginx