# Workshop: Nginx Reverse Proxy Server
WARNING
- Please prepare one folder for this Workshop
# Start Coding (Dev environment)
# project structure
+-- backend
| +-- src
| | +-- main.py
| | +-- mongo_connector.py
| +-- dev.Dockerfile
+-- frontend
| +-- src
| | +-- app.js
| | +-- index.html
| +-- dev.Dockerfile
+-- nginx
| +-- Dockerfile
| +-- nginx.conf
+-- docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
./docker-compose.yml
version: "3"
services:
nginx:
build:
context: ./nginx
ports:
- "80:80"
frontend:
build:
context: ./frontend
dockerfile: dev.Dockerfile
volumes:
- ./frontend/src:/usr/share/nginx/html
backend:
build:
context: ./backend
dockerfile: dev.Dockerfile
volumes:
- ./backend/src:/home/src
mongo:
image: mongo:3.6.22-xenial
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 1234
volumes:
- mongo-sad-lab-nginx-proxy:/data/db
volumes:
mongo-sad-lab-nginx-proxy: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Backend
./backend/dev.Dockerfile
FROM python:3.9.7-buster
WORKDIR /home/src
RUN pip install "fastapi==0.70.0"
RUN pip install uvicorn[standard]
RUN pip install "pymongo==3.12.0"
RUN pip install "mypy==0.910"
EXPOSE 8000
CMD uvicorn --host 0.0.0.0 main:app --forwarded-allow-ips '*' --reload 1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
./backend/src/main.py
from fastapi import FastAPI
from mongo_connector import Mongo
app = FastAPI()
base_url = "/api"
@app.get(base_url+"/")
def read_root():
data = Mongo.get_instance()['my-db']['my-collection'].find_one({"name":"counter"},{'_id':0})
return data
@app.get(base_url+"/count")
def add_count():
data = Mongo.get_instance()['my-db']['my-collection'].update_one({"name":"counter"},{"$inc":{"value":1}})
return {"result":data.modified_count}
def init_obj():
data = [ d for d in Mongo.get_instance()['my-db']['my-collection'].find({"name":"counter"})]
if(not data):
new_data = {
"name":"counter",
"value": 0
}
Mongo.get_instance()['my-db']['my-collection'].insert_one(new_data)
init_obj()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
./backend/src/mongo_connector.py
import pymongo #type:ignore
from pymongo.mongo_client import MongoClient #type:ignore
import os
class Mongo:
username="root"
password=1234
hostname="mongo"
uri=f"mongodb://{username}:{password}@{hostname}:27017"
client:MongoClient
@staticmethod
def init():
if('MONGO_STRING_OPTIONS' in os.environ):
Mongo.uri+=os.environ['MONGO_STRING_OPTIONS']
temp=pymongo.MongoClient(Mongo.uri)
Mongo.client=temp
@staticmethod
def get_instance():
if not hasattr(Mongo,'client'):
Mongo.init()
return Mongo.client 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Frontend
./frontend/dev.Dockerfile
FROM nginx:stable-alpine
CMD ["nginx", "-g", "daemon off;"] 1
2
2
./frontend/src/app.js
const outputDom = document.getElementById("output-dom")
const getData = async() => {
const response = await fetch("/api")
const jsonText = await response.json()
outputDom.innerHTML = JSON.stringify(jsonText)
}
const addCount = async() => {
const response = await fetch("/api/count")
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
./frontend/src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick="addCount()">click here for adding</button>
<button onclick="getData()">click here for getting</button>
<h1 id="output-dom"></h1>
<script src="./app.js"></script>
</body>
</html> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Nginx Configuration
./nginx/Dockerfile
FROM nginx
COPY ./nginx.conf /etc/nginx/nginx.conf 1
./nginx/nginx.conf
events {
}
http {
upstream front{
server frontend:80;
}
upstream apiV1 {
server backend:8000;
}
server {
listen 80;
location /api {
proxy_pass http://apiV1;
}
location / {
proxy_pass http://front;
}
}
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Up
docker-compose up --build -d
1
# Down and finish this session
docker-compose down
1
# Start Coding (Production)
+-- backend
| +-- src
| | +-- main.py
| | +-- mongo_connector.py
| +-- dev.Dockerfile
| +-- prod.Dockerfile
+-- frontend
| +-- src
| | +-- app.js
| | +-- index.html
| +-- dev.Dockerfile
| +-- prod.Dockerfile
+-- nginx
| +-- Dockerfile
| +-- nginx.conf
+-- docker-compose.yml
+-- docker-compose-prod.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
./docker-compose-prod.yml
version: "3"
services:
nginx:
build:
context: ./nginx
ports:
- "80:80"
frontend:
build:
context: ./frontend
dockerfile: prod.Dockerfile
backend:
build:
context: ./backend
dockerfile: prod.Dockerfile
mongo:
image: mongo:3.6.22-xenial
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 1234
volumes:
- mongo-sad-lab-nginx-proxy:/data/db
volumes:
mongo-sad-lab-nginx-proxy: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Backend
./backend/prod.Dockerfile
FROM python:3.9.7-buster
WORKDIR /home/src
RUN pip install "fastapi==0.70.0"
RUN pip install uvicorn[standard]
RUN pip install "pymongo==3.12.0"
COPY ./src /home/src/
EXPOSE 8000
CMD uvicorn --host 0.0.0.0 main:app --forwarded-allow-ips '*' 1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- Remove Dev Dependency (In this case is mypy (opens new window).)
- FastAPI would be production ready if we remove --reload.
# Frontend
./frontend/prod.Dockerfile
FROM nginx:stable-alpine
COPY ./src /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]1
2
3
4
2
3
4
# Up
docker-compose -f ./docker-compose-prod.yml up --build -d
1
# Down and finish this lab
docker-compose -f ./docker-compose-prod.yml down
1