Publishing Two Sites with Django/Docker/Nginx Reverse Proxy? - django

How can I publish two different Django projects with two domains to one host using Docker in my DigitalOcean Droplet? Should I set Nginx in the docker-compose.yml file, or should I set it on the host system (etc/nginx/…)? Or should I run nginx in a separate container?
When I search on the internet, people who publish django projects with docker usually write their nginx settings in the docker-compase.yml file, but I couldn't understand how to set the reverse proxy in this way to publish two different sites.
Nginx settings - Dockerfile, docker-compose.yml would be very appreciated if you give information about settings. Thanks in advance.
I'm sorry for my bad English :( :(
docker-compose.yml
version: '3'
services:
djangoapp:
build: .
volumes:
- .:/opt/services/djangoapp/src
- static_volume:/opt/services/djangoapp/static
- media_volume:/opt/services/djangoapp/media
networks:
- nginx_network
- database1_network
depends_on:
- database1
nginx:
image: nginx
ports:
- 8000:80
volumes:
- ./config/nginx/conf.d:/etc/nginx/conf.d
- static_volume:/opt/services/djangoapp/static
- media_volume:/opt/services/djangoapp/media
depends_on:
- djangoapp
networks:
- nginx_network
database1:
image: postgres
env_file:
- config/db/database1_env
networks:
- database1_network
volumes:
- database1_volume:/var/lib/postgresql/data
networks:
nginx_network:
driver: bridge
database1_network:
driver: bridge
volumes:
database1_volume:
static_volume:
media_volume:
Nginx - local.conf
upstream hello_server {
server djangoapp:8000;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://hello_server;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8000;
}
location /static/ {
alias /opt/services/djangoapp/static/;
}
location /media/ {
alias /opt/services/djangoapp/media/;
}
}
Dockerfile
FROM python:3.8
RUN mkdir -p /opt/services/djangoapp/src
WORKDIR /opt/services/djangoapp/src
COPY Pipfile Pipfile.lock /opt/services/djangoapp/src/
RUN pip install pipenv && pip install --upgrade pip && pipenv install --system
RUN pip install django-ckeditor
RUN pip install Pipfile
COPY . /opt/services/djangoapp/src
EXPOSE 8000
CMD ["gunicorn", "--chdir", "hello", "--bind", ":8000", "hello.wsgi:application"]

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:

configuring django with nginx gunicorn on docker

Good day, I am new to docker and I have a Django app I will like to dockerize, I have searched for tutorials to help me set up my Django app with docker, I followed this article here on test-driven https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/. I get issues making nginx work with my app. here is my code.
my apps docker file:
FROM python:3.8-alpine
ENV PATH="/scripts:${PATH}"
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
RUN mkdir /app
COPY ./testdocker /app
WORKDIR /app
COPY ./scripts /scripts
RUN chmod +x /scripts/*
RUN mkdir -p /vol/web/media
RUN mkdir -p /vol/web/static
RUN adduser -D user
RUN chown -R user:user /vol
RUN chmod -R 755 /vol/web
USER user
nginx docker file:
FROM nginx:1.19.3-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY ./nginx.conf /etc/nginx/conf.d
RUN mkdir -p /vol/static
my docker-compose file:
version: '3.7'
services:
app:
build:
context: .
command: sh -c "gunicorn testdocker.wsgi:application --bind 0.0.0.0:8000"
volumes:
- static_data:/vol/web
expose:
- "8000"
environment:
- SECRET_KEY=MANME1233
- ALLOWED_HOSTS=127.0.0.1, localhost
nginx:
build:
context: ./nginx
volumes:
- static_data:/vol/static
ports:
- "8080:80"
depends_on:
- app
volumes:
static_data:
my nginx conf file:
upstream testapp {
server app:8000;
}
server {
listen 8080;
server_name app;
location / {
proxy_pass http://testapp;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static {
alias /vol/static;
}
}
I can't seem to get nginx to reverse proxy to my web app, upon opening the URL on the browser I get a 404 bad request or address not found. please what am I doing wrong or not doing right?.
#victormazeli It looks like you missed placing your services within the same docker network and I see some misconfiguration in nginx conf file. Try updating your docker-compose.yml as follows:
version: '3.7'
services:
app:
build:
context: .
command: sh -c "gunicorn testdocker.wsgi:application --bind 0.0.0.0:8000"
volumes:
- static_data:/vol/web
expose:
- "8000"
environment:
- SECRET_KEY=MANME1233
- ALLOWED_HOSTS=127.0.0.1, localhost
networks:
- main
nginx:
build:
context: ./nginx
volumes:
- static_data:/vol/static
ports:
- "8080:80"
depends_on:
- app
networks:
- main
volumes:
static_data:
networks:
main:
Then, update your nginx config as follows:
server {
server_name nginx;
listen 80;
location /static {
alias /vol/static;
}
location / {
proxy_pass http://app:8000/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
Another thing to keep in mind here is that you have 2 targets that are being served by the NGINX reverse-proxy:
Django project located in testdocker which should be accessible via localhost:8080
Static file data which is accessible via localhost:8080/static/[relative_path]
To access the static data, you will need the path relative to /vol/static in nginx service (which is a docker volume mount also mounted to /vol/web in app service). According to app's Dockerfile, the static_data volume should contain 2 directories: media and static. Therefore, if you have say an index.html located in directory /vol/web/static in app service, it should be accessible via localhost:8080/static/static/index.html.
Give this a try and let me know how it works out for you.

Nginx not serving media files. Dockerizing django/nginx/gunicorn/postgresql

I have a project running in 3 docker containers. One is for django project itself, another one for postgres and the third one for nginx. My static files are served just fine while all media files are not found. However every file which was uploaded is properly saved in web container in media folder.
Here is the docker-compose file:
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 foodgram.wsgi:application --bind 0.0.0.0:8000
volumes:
- ./static:/static
- ./media:/media
ports:
- "8000:8000"
depends_on:
- db
env_file:
- ./.env
nginx:
build:
context: .
dockerfile: nginx/Dockerfile
ports:
- "8080:80"
volumes:
- ./static:/etc/nginx/html/static
- ./media:/etc/nginx/html/media
depends_on:
- web
Here is the dockerfile:
FROM python:3.8.5
WORKDIR /code
COPY . /code
RUN pip install -r /code/requirements.txt
Here is the nginx.conf:
events {}
http {
include mime.types;
server {
location / {
proxy_pass http://web:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
location /static/ {
autoindex on;
root /etc/nginx/html/;
}
location /media/ {
autoindex on;
root /etc/nginx/html/;
}
}
}
and finally nginx dockerfile:
FROM nginx:latest
COPY nginx/nginx.conf /etc/nginx/nginx.conf
Error returned:
19#19: *1 open() "/etc/nginx/html/media/4.jpg" failed (2: No such file or directory)
There are no nested folders in media/static folders.

I'm trying to deploy Django on Docker in AWS Lightsail, and the pages are stuck loading with no connection to server

I have been trying to deploy a Django app on Lightsail with Gunicorn, NginX, and Docker. I've looked at multiple tutorials, all without success. I'm not familiar with most of the concepts, and I've pretty much been following blindly. So far, everything seems to work on the server itself, but I can't see the results on a webpage. I have configured it for "production" (not sure if I'm even doing it right), and I've added a record to my domain which redirects to this server. The webpage just buffers continuously, even when I try to set it to port 8000 (for development). I think I've gotten a few instances where I saw a "301 5" permanently moved log show up on the docker-compose logs, but that's about it.
Here are the Dockerfile, docker-compose.yml, and nginx conf.d file (which are probably the most important.
docker-compose.yml
version: '3.7'
services:
web:
build:
environment:
- ENVIRONMENT=production
- SECRET_KEY=NOT IMPORTANT
- DEBUG=0
- EMAIL_HOST_USER=EMAIL
- EMAIL_HOST_PASSWORD=PASSWORD
volumes:
- .:/code
- static_volume:/code/staticfiles
depends_on:
- db
networks:
- nginx_network
- db_network
db:
image: postgres:11
env_file:
- config/db/db_env
networks:
- db_network
volumes:
- db_volume:/var/lib/postgresql/data
nginx:
image: nginx:1.17.0
ports:
- 80:80
volumes:
- ./config/nginx/conf.d:/etc/nginx/conf.d
- static_volume:/code/staticfiles
depends_on:
- web
networks:
- nginx_network
networks:
nginx_network:
driver: bridge
db_network:
driver: bridge
volumes:
db_volume:
static_volume:
Dockerfile:
# Pull base image
FROM python:3.7
# Environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Work directory
WORKDIR /code
# Dependencies
COPY Pipfile Pipfile.lock /code/
RUN pip install pipenv && pipenv install --system
# Copy project
COPY . /code/
# expose port
EXPOSE 80
# gunicorn
CMD ["gunicorn", "--chdir", "my_project", "--bind", ":80", "mbdebate_project.wsgi:application"]
conf.d:
upstream hello_server {
server web:80;
}
server {
listen 80;
server_name mydomain.com;
location / {
proxy_pass http://hello_server;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /code/staticfiles/;
}
}
The settings are pretty standard, and I don't think the problem is there. Any help would truly be appreciated :).
The tutorial I followed: tpawamoy.github.io/2018/02/01/docker-compose-django-postgres-nginx.html
When working on a flask application I had a similar issue connecting with nginx.
On nginx.conf, I used the same host configuration in my app.run.
Change web:80; in your conf.d to the host exposed by Django application.**
My case:-
app.py
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
nginx.conf
upstream flask-app {
server 0.0.0.0:5000;
}
server {
listen 80 default_server;
# https for production
location / {
proxy_pass http://flask-app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}