Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dockerize frontend + nginx #8

Open
wants to merge 9 commits into
base: rest
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ db.sqlite3

# production
/build
/nginx/cert

# misc
.DS_Store
Expand Down
4 changes: 3 additions & 1 deletion eews_backend/database/mongodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
def mongo_client():
mongo_url = MONGO_URL
mongo_db = MONGO_DATABASE
client = motor_asyncio.AsyncIOMotorClient(mongo_url)
MONGO_USERNAME = os.getenv("MONGO_USERNAME")
MONGO_PASSWORD = os.getenv("MONGO_PASSWORD")
client = motor_asyncio.AsyncIOMotorClient(mongo_url, username=MONGO_USERNAME, password=MONGO_PASSWORD)
db = client[mongo_db]
return client, db
2 changes: 1 addition & 1 deletion eews_backend/rest/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

ENV PORT 8000
ENV PORT 80
EXPOSE $PORT
RUN pip install --no-cache-dir -r requirements.txt

Expand Down
34 changes: 21 additions & 13 deletions eews_backend/rest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,18 @@
MODULE_DIR = "./rest/"
STATIC_DIR = "static/"
SIMULATE_REALTIME = False if os.getenv("SIMULATE_REALTIME") == "False" else True
MSEED_RANGE_IN_SECONDS = 30
SIMULATE_DATETIME = os.getenv("SIMULATE_DATETIME")
LENGTH_DATA_IN_SECONDS = int(os.getenv("LENGTH_DATA_IN_SECONDS"))
MSEED_RANGE_IN_SECONDS = int(os.getenv("MSEED_RANGE_IN_SECONDS"))
BACKEND_IP = os.getenv("BACKEND_IP") if os.getenv("BACKEND_IP") else "localhost"
FRONTEND_IP = os.getenv("FRONTEND_IP") if os.getenv("FRONTEND_IP") else "localhost"

origins = [
"http://host.docker.internal",
"http://localhost",
"http://localhost:3000",
f"http://{BACKEND_IP}",
f"http://{FRONTEND_IP}"
]

app = FastAPI()
Expand All @@ -75,7 +82,7 @@
_, db = mongo_client()
client = influx_client()

HTML = """
HTML = f"""
<!DOCTYPE html>
<html>
<head>
Expand All @@ -90,7 +97,7 @@
<ul id='messages'>
</ul>
<script>
var ws = new WebSocket("ws://localhost:8000/ws");
var ws = new WebSocket("ws://{BACKEND_IP}:80/ws"); """ + """
ws.onmessage = function(event) {
var messages = document.getElementById('messages')
var message = document.createElement('li')
Expand Down Expand Up @@ -163,10 +170,10 @@ async def post():
@app.get("/test")
async def test():
query_api = client.query_api()
now = datetime(2015, 8, 20, 15, 11, 47, tzinfo=timezone.utc)
now = parser.parse(SIMULATE_DATETIME) # Date for simulation purposes
query = f"""
from(bucket: "eews")
|> range(start: {(now - timedelta(seconds=1)).isoformat()}, stop: {now.isoformat()})
|> range(start: {(now - timedelta(seconds=LENGTH_DATA_IN_SECONDS)).isoformat()}, stop: {now.isoformat()})
|> filter(fn: (r) => r["_measurement"] == "p_arrival" or r["_measurement"] == "seismograf")"""
data: TableList = query_api.query(query=query)
result = {}
Expand Down Expand Up @@ -201,7 +208,7 @@ async def test():
await db["prediction"]
.find(
{
"p-arrival": {"$lte": now - timedelta(seconds=1)},
"p-arrival": {"$lte": now - timedelta(seconds=LENGTH_DATA_IN_SECONDS)},
"expired": {"$gte": now},
}
)
Expand All @@ -210,7 +217,7 @@ async def test():
for p in prediction:
del p["_id"]

print(now - timedelta(seconds=1))
print(now - timedelta(seconds=LENGTH_DATA_IN_SECONDS))
print(now)
return {"data": result, "prediction": prediction}
# return extended_data.to_dict()
Expand All @@ -226,16 +233,17 @@ async def websocket_endpoint(websocket: WebSocket):
await manager.connect(websocket)
try:
query_api = client.query_api()
now = datetime(2015, 8, 20, 15, 11, 47, tzinfo=timezone.utc)
now = parser.parse(SIMULATE_DATETIME) # Date for simulation purposes
if SIMULATE_REALTIME:
now = datetime.now(tz=timezone.utc) - timedelta(
seconds=MSEED_RANGE_IN_SECONDS
seconds = MSEED_RANGE_IN_SECONDS # Realtime delay from seedlink
)
while True:
start = time.monotonic_ns()
# Query LENGTH_DATA_IN_SECONDS worth of data
query = f"""
from(bucket: "eews")
|> range(start: {(now - timedelta(seconds=1)).isoformat()}, stop: {now.isoformat()})
|> range(start: {(now - timedelta(seconds=LENGTH_DATA_IN_SECONDS)).strftime("%Y-%m-%dT%H:%M:%S.%fZ")}, stop: {now.strftime("%Y-%m-%dT%H:%M:%S.%fZ")})
|> filter(fn: (r) => r["_measurement"] == "p_arrival" or r["_measurement"] == "seismograf")"""
data: TableList = query_api.query(query=query)
result = {}
Expand Down Expand Up @@ -270,7 +278,7 @@ async def websocket_endpoint(websocket: WebSocket):
await db["prediction"]
.find(
{
"p-arrival": {"$lte": now - timedelta(seconds=1)},
"p-arrival": {"$lte": now - timedelta(seconds=LENGTH_DATA_IN_SECONDS)},
"expired": {"$gte": now},
}
)
Expand All @@ -282,10 +290,10 @@ async def websocket_endpoint(websocket: WebSocket):
del p["expired"]

json_data = json.dumps({"data": result, "prediction": prediction})
now += timedelta(seconds=1)
now += timedelta(seconds=LENGTH_DATA_IN_SECONDS)
await manager.broadcast(json_data)
diff = (time.monotonic_ns() - start) / 10**9
await asyncio.sleep(1 - diff)
await asyncio.sleep(LENGTH_DATA_IN_SECONDS - diff)
except Exception as e:
log.error(e)
log.warning(f"Client {websocket} has been disconnected")
Expand Down
37 changes: 37 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# stage1 as builder
FROM node:14 as builder

# copy the package.json to install dependencies
COPY /frontend/package.json /frontend/package-lock.json ./

# Install the dependencies and make the folder
RUN npm install && mkdir /frontend && mv ./node_modules ./frontend

WORKDIR /frontend

COPY /frontend .

# Backend IP
ARG REACT_APP_API
ENV REACT_APP_API 34.101.239.0:80

# Build the project and copy the files
RUN npm run build


FROM nginx:alpine

#!/bin/sh

COPY /nginx/webserver.conf /etc/nginx/nginx.conf
COPY /nginx/cert/ /etc/nginx/cert

## Remove default nginx index page
RUN rm -rf /usr/share/nginx/html/*

# Copy from the stahg 1
COPY --from=builder /frontend/build /usr/share/nginx/html

EXPOSE 80 443

ENTRYPOINT ["nginx", "-g", "daemon off;"]
1 change: 1 addition & 0 deletions frontend/public/_redirects
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* /index.html 200
4 changes: 2 additions & 2 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
<script>
<!-- <script>
document.addEventListener('DOMContentLoaded', function() {
const loadEl = document.querySelector('#load');
// // 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
Expand Down Expand Up @@ -85,5 +85,5 @@
loadEl.textContent = 'Error loading the Firebase SDK, check the console.';
}
});
</script>
</script> -->
</html>
10 changes: 0 additions & 10 deletions frontend/public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ import About from "./pages/About";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

const App = () => {
var api = process.env.NODE_ENV == 'production'? process.env.REACT_APP_API : 'localhost';
return (
<Router>
<Navibar />
<Routes>
<Route exact path="/" element={<AdminMap url={"localhost:8000"} />} />
<Route exact path="/" element={<AdminMap url={api} />} />
<Route path="/about" element={<About />} />
<Route
path="/admin-map"
element={<AdminMap url={"localhost:8000"} />}
element={<AdminMap url={api} />}
/>
<Route path="/login" element={<LogIn />} />
<Route path="/help" element={<Help />} />
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Map/Map2.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const Map = (props) => {
jsonData.forEach((element) => {
L.marker(
[
element["location"]["coordinates"][0],
element["location"]["coordinates"][1],
element["location"]["coordinates"][1], // latitude
element["location"]["coordinates"][0], // longitude
],
{ icon: customMarkerIcon(element["name"]) }
)
Expand Down
88 changes: 88 additions & 0 deletions nginx/webserver.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
log_format custom '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"'
' Proxy: "$proxy_host" "$upstream_addr"';

access_log /var/log/nginx/access.log custom;

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

upstream backend {
ip_hash;
server 127.0.1.1;
server 127.0.1.2;
}

server {
listen 80;
listen 443 ssl;

root /usr/share/nginx/html;
include /etc/nginx/mime.types;

ssl_certificate /etc/nginx/cert/eews.crt;
ssl_certificate_key /etc/nginx/cert/eews.key;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
ssl_prefer_server_ciphers on;

location / {
try_files $uri $uri/ /index.html;
}

location ~ ^/api(/.*)$ {
proxy_pass http://backend$1;
}

location ~ .*(\/ws)$ {
proxy_pass http://backend$1;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header Origin "http://localhost";
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin $http_origin;
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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;

proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
}
}

server {
listen 127.0.1.1;

location / {
proxy_pass http://34.101.239.0:80;
}
}

server {
listen 127.0.1.2;

location / {
proxy_pass http://34.101.45.253:80;
}
}
}