400 Bad Request The plain HTTP request was sent to HTTPS port, while Deploying Django to AWS with Docker and Let's Encrypt - reactjs

I am following the "Django on Docker Series" series by testdrivenio(https://testdriven.io/blog/django-docker-https-aws/) for deploying a project into a new domain. I am using Django as backend but when I try to access the backend url via the port it showing via docker ps command i.e.,
http://0.0.0.0:443/
I get the following error,
This is the docker-compose file I am using
version: '3.7'
services:
web:
build:
context: ./myprojectname
dockerfile: Dockerfile.staging
image: 789497322711.dkr.ecr.us-east-3.amazonaws.com/myprojectname-staging:web
command: gunicorn myprojectname.wsgi:application --bind 0.0.0.0:8005
volumes:
- static_volume:/home/myprojectname_staging/web/static
- media_volume:/home/myprojectname_staging/web/media
expose:
- 8000
env_file:
- ./.env.staging
frontendimage:
container_name: frontendimage
image: 789497322711.dkr.ecr.us-east-3.amazonaws.com/myprojectname-staging:frontendimage
stdin_open: true
build:
context: .
dockerfile: frontend/Dockerfile.staging
# volumes:
# - type: bind
# source: ./frontend
# target: /usr/src/frontend
# - '.:/usr/src/frontend'
# - '/usr/src/frontend/node_modules'
ports:
- '1337:30'
environment:
- CHOKIDAR_USEPOLLING=true
depends_on:
- web
nginx-proxy:
container_name: nginx-proxy
build: ./myprojectname/nginx
image: 789497322711.dkr.ecr.us-east-3.amazonaws.com/myprojectname-staging:nginx-proxy
restart: always
ports:
- 443:443
- 80:80
volumes:
- static_volume:/home/myprojectname_staging/web/staticfiles
- media_volume:/home/myprojectname_staging/web/mediafiles
- certs:/etc/nginx/certs
- html:/usr/share/nginx/html
- vhost:/etc/nginx/vhost.d
- /var/run/docker.sock:/tmp/docker.sock:ro
depends_on:
- web
nginx-proxy-letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
env_file:
- .env.staging.proxy-companion
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- certs:/etc/nginx/certs
- html:/usr/share/nginx/html
- vhost:/etc/nginx/vhost.d
depends_on:
- nginx-proxy
volumes:
static_volume:
media_volume:
certs:
html:
vhost:
My Nginx directory
└── nginx
├── Dockerfile
├── custom.conf
└── vhost.d
└── default
Dockerfile
FROM jwilder/nginx-proxy
COPY vhost.d/default /etc/nginx/vhost.d/default
COPY custom.conf /etc/nginx/conf.d/custom.conf
custom.conf
client_max_body_size 10M;
default
server {
listen 80;
listen 443 default ssl;
}
location /static/ {
alias /home/myprojectname_staging/web/static/;
add_header Access-Control-Allow-Origin *;
}
location /media/ {
alias /home/myprojectname_staging/web/media/;
add_header Access-Control-Allow-Origin *;
}
What should be my next course of action?

Related

Connection between two docker containers in nextjs in getStaticProps function

I have two separate docker files, one for running nextjs on nginx web server and another for running Laravel on another nginx:
services:
frontendx:
container_name: next_appx
build:
context: ./frontend
dockerfile: Dockerfile
restart: unless-stopped
volumes:
- ./frontend:/var/www/html/frontend
networks:
- app
nginxy:
container_name: nginxy
image: nginx:1.19-alpine
restart: unless-stopped
ports:
- '8080:80'
volumes:
- ./frontend:/var/www/html/frontend
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- frontendx
networks:
- app
and:
services:
backendx:
container_name: laravelx
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
ports:
- '8000:8000'
volumes:
- ./:/var/www
- enlive-vendor:/var/www/vendor
- .//docker-xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
depends_on:
- dbx
networks:
- appx
webserverx:
image: nginx:alpine
container_name: webserverx
restart: unless-stopped
tty: true
ports:
- "8090:80"
- "443:443"
volumes:
- ./:/var/www
- ./nginx/conf.d/:/etc/nginx/conf.d/
networks:
- appx
I can connect to the backend container through axios and address like : http://localhost:8090/api/my/api/address
but when I try to get data through getStaticProps I've got the ECONNREFUSED connection error:
const res = await fetch(`http://localhost:8090/api/address`)
I tried to replace the localhost with container ip address like : 172.20.0.2
but I've got the 504 Gateway error.
That's expected.
With axios, you're calling from the browser which is making the request from your host machine network.
But getStaticProps being a SSR function, is run inside your nextjs container. Therefore it must be able to find your backend in your app network.
Now by your setup, the frontend and backend apps are in different isolated networks and you can't connect them like this. But if you put them all your services in the same network, lets say your app(instead of appx) network, you can easily use docker dns:
const res = await fetch(`http://webserverx/api/address`)
Docker knows how to resolve webserverx to your webserverx container.

NGINX Reverse Proxy with multiple locations for multiple containers

I am trying to run two React applications and an API server in an EC2 instance and reverse-proxy using NGINX using docker-compose.
When I navigate to example.com, the client app is loaded as expected. However, when I navigate to example.com/admin the admin app is not loaded. The tab name and icon are the ones of the admin app, however the page is completely blank. I am sure it is not the admin app the problem because if I change the proxy_pass directive in the default.conf file for the / location it is loaded as expected. What am I missing then?
Hereafter is the default.conf for NGINX (HTTPS is not implemented yet):
server {
server_name www.example.com;
rewrite ^(.*) http://example.com$1 permanent;
}
server {
listen 80;
listen [::]:80;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
proxy_pass http://client:3000;
}
location /admin {
proxy_pass http://admin:3001;
}
location /api {
proxy_pass http://server:5000;
}
location ~ /.well-known/acme-challenge {
allow all;
try_files $uri =404;
break;
}
}
Hereafter is the docker-compose.yml file:
version: '3.7'
services:
client:
image: app_client
container_name: client
restart: unless-stopped
hostname: client
ports:
- '3000:3000'
networks:
- network
admin:
image: app_admin
container_name: admin
restart: unless-stopped
hostname: admin
ports:
- '3001:3001'
networks:
- network
mongodb:
image: app_mongodb
container_name: mongodb
restart: unless-stopped
hostname: mongodb
volumes:
- mongo-data:/data/db
ports:
- '27017:27017'
networks:
- network
server:
image: app_server
container_name: server
restart: unless-stopped
hostname: server
ports:
- '5000:5000'
depends_on:
- mongodb
networks:
- network
proxy:
image: app_proxy
container_name: proxy
hostname: proxy
restart: unless-stopped
ports:
- '80:80'
- '443:443'
volumes:
- web-root:/var/www/html
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
depends_on:
- client
- server
networks:
- network
certbot:
...
networks:
network:
driver: bridge
volumes:
mongo-data:
driver: local
certbot-etc:
certbot-var:
web-root:
driver: local
try this:
location ^~ /admin/ {
rewrite /admin/(.*) /$1 break;
proxy_pass http://0.0.0.0:3001;
}

Docker is not saving django media files into project 'media' directory on production

App Description
I have an app with django-gunicorn for back-end and reactjs-nginx with front-end all containerized as well as hosted on aws ec2 instance.
Problem
On development environment, media files are being saved in the 'media' directory permanently. Tho, those files are only saved on the current running docker container on production time. As a result, the files will be removed when I rebuild/stopped the container for a new code push.
Expectation
I wanted to store the file on the 'media' folder for permanent use.
Important code
settings.py
ENV_PATH = Path(__file__).resolve().parent.parent
STATIC_ROOT = BASE_DIR / 'django_static'
STATIC_URL = '/django_static/'
MEDIA_ROOT = BASE_DIR / 'media/'
MEDIA_URL = '/media/'
docker-compose-production.yml
version: "3.3"
services:
db:
image: postgres
restart: always #Prevent postgres from stopping the container
volumes:
- ./data/db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
ports:
- 5432:5432
nginx:
restart: unless-stopped
build:
context: .
dockerfile: ./docker/nginx/Dockerfile
ports:
- 80:80
- 443:443
volumes:
- static_volume:/code/backend/server/django_static
- ./docker/nginx/production:/etc/nginx/conf.d
- ./docker/nginx/certbot/conf:/etc/letsencrypt
- ./docker/nginx/certbot/www:/var/www/certbot
depends_on:
- backend
# Volume for certificate renewal
certbot:
image: certbot/certbot
restart: unless-stopped
volumes:
- ./docker/nginx/certbot/conf:/etc/letsencrypt
- ./docker/nginx/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
backend:
restart: unless-stopped
build:
context: .
dockerfile: ./docker/backend/Dockerfile
entrypoint: /code/docker/backend/wsgi-entrypoint.sh
volumes:
- .:/code
- static_volume:/code/backend/server/django_static
expose:
- 8000
depends_on:
- db
volumes:
static_volume: { }
pgdata: { }
I finally figured out the issue. I forgot to add .:/code to my nginx volumes config in my docker-compose file. Thank to this answer
Updated nginx volumes confi
volumes:
- .:/code
- static_volume:/code/backend/server/django_static
- ./docker/nginx/production:/etc/nginx/conf.d
- ./docker/nginx/certbot/conf:/etc/letsencrypt
- ./docker/nginx/certbot/www:/var/www/certbot

Dockerize React-Django App and serving on Nginx server Error : 502 Bad Gateway

I have four containers and I am trying to serve the client on Nginx server, but I am getting 502 Bad Gateway. I would assume that'd be because my address port is wrong but I have correct port forwarding as far as I can tell. I'd appreciate any help here, how to resolve it. Thanks
docker-compose.yml
version: "3.7"
services:
backend:
container_name: backend
build: ./backend
command: >
sh -c "python backend/manage.py makemigrations
&& python backend/manage.py runserver 0.0.0.0:8000"
volumes:
- ./backend:/app/backend
environment:
- "DATABASE_URL=postgres://postgres:postgres#db:5432/postgres"
expose:
- 8000
stdin_open: true
tty: true
depends_on:
- db
db:
container_name: db
build: ./db
ports:
- 5432:5432
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
frontend:
container_name: client
build: ./client
volumes:
- ./client:/app/client
- /app/client/node_modules
expose:
- 3000
stdin_open: true
tty: true
environment:
- NODE_ENV=development
depends_on:
- backend
nginx:
container_name: webserver
build: ./webserver
links:
- frontend
- backend
depends_on:
- frontend
- backend
ports:
- "8080:80"
volumes:
postgres_data:
Nginx - Dockerfile
FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx-proxy.conf /etc/nginx/conf.d
nginx-proxy.conf
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://client:3000;
}
location /api {
rewrite ^/api(.*) $1 break;
proxy_pass http://backend:8000;
}
}
Result
It should be name of service; frontend, not container_name client
proxy_pass http://frontend:3000;

Deploying with docker-compose. Frontend is not reaching backend

So I'm running a web app which consist of 3 services with docker-compose.
A mongodb database container.
A nodejs backend.
A nginx container with static build folder which serves a react app.
Locally it runs fine and I'm very happy, when trying to deploy to a vps I'm facing an issue.
I've set the vps' nginx to reverse proxy to port 8000 which serves the react app, it runs as expected but I can not send requests to the backend, when I'm logged in the vps I can curl it and it responds, but when the web app sends requests, they hang.
My docker-compose:
version: '3.7'
services:
server:
build:
context: ./server
dockerfile: Dockerfile
image: server
container_name: node-server
command: /usr/src/app/node_modules/.bin/nodemon server.js
depends_on:
- mongo
env_file: ./server/.env
ports:
- '8080:4000'
environment:
- NODE_ENV=production
networks:
- app-network
mongo:
image: mongo:4.2.7-bionic
container_name: database
hostname: mongo
environment:
- MONGO_INITDB_ROOT_USERNAME=...
- MONGO_INITDB_ROOT_PASSWORD=...
- MONGO_INITDB_DATABASE=admin
restart: always
ports:
- 27017:27017
volumes:
- ./mongo/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
networks:
- app-network
client:
build:
context: ./client
dockerfile: prod.Dockerfile
image: client-build
container_name: react-client-build
env_file: ./client/.env
depends_on:
- server
ports:
- '8000:80'
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
data-volume:
node_modules:
web-root:
driver: local

Resources