Skip to content

Commit 6d00341

Browse files
authored
Merge pull request #147 from dcdenu4/feature/vm-hosting
Merge in current hosting branch, which is our active server
2 parents 77ec6e8 + dca5e9e commit 6d00341

File tree

17 files changed

+542
-50
lines changed

17 files changed

+542
-50
lines changed

README.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,33 @@ scenarios using InVEST Urban models.
55

66
## Setup with docker compose
77

8+
The application can be run in dev and production mode using docker compose
9+
profiles. Production mode is meant to be run on a preconfigured GCE Linux VM.
10+
11+
### Dev mode
12+
```shell
13+
$ docker compose --profile dev up
14+
```
15+
16+
or if you want to force a rebuild of the containers,
17+
18+
```shell
19+
$ docker compose --profile dev up --build
20+
```
21+
22+
### Prod mode
823
```shell
9-
$ docker compose up
24+
$ docker compose --profile prod up
1025
```
1126

1227
or if you want to force a rebuild of the containers,
1328

1429
```shell
15-
$ docker compose up --build
30+
$ docker compose --profile prod up --build
1631
```
1732

18-
## App runs on
19-
`http://localhost:3000`
33+
## App runs on (dev mode)
34+
`http://localhost:80`
2035

2136
## View fastapi endpoint documentation
2237
`http://localhost:8000/docs`

backend-worker/Dockerfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
# syntax=docker/dockerfile:1
22
# forcing --platform=linux/amd64 because we don't have arm builds of our conda-forge packages yet
33
FROM --platform=linux/amd64 mambaorg/micromamba:0.24.0-buster
4-
4+
USER root
5+
RUN mkdir /opt/appdata
6+
RUN chmod -R 777 /opt/appdata
7+
USER $USER
58
ARG MAMBA_DOCKERFILE_ACTIVATE=1
6-
RUN micromamba install -c conda-forge -y pygeoprocessing natcap.invest=3.14.1 requests flask_cors pillow geopandas
9+
RUN micromamba install -c conda-forge -y "sqlite<=3.48" "libsqlite<=3.48" pygeoprocessing natcap.invest=3.14.3 requests flask_cors pillow geopandas
710

811
CMD /opt/conda/bin/python

backend-worker/invest_results.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ def carbon(workspace_dir):
8080

8181
carbon_results = {}
8282
for output, output_path in carbon_outputs.items():
83-
carbon_results[output] = pygeoprocessing.raster_reduce(
84-
lambda total, block: total + numpy.sum(block), (output_path, 1), 0)
83+
# Cast to float because numpy.float32 is not JSON serializable
84+
carbon_results[output] = float(pygeoprocessing.raster_reduce(
85+
lambda total, block: total + numpy.sum(block), (output_path, 1), 0))
8586

8687
results_json_path = os.path.join(workspace_dir, "derived_results.json")
8788
with open(results_json_path, "w") as fp:

backend-worker/worker.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
_LULC_RASTER_INFO = pygeoprocessing.get_raster_info(LULC_RASTER_PATH)
6262
except ValueError:
6363
LOGGER.info(f"Could not open raster path {LULC_RASTER_PATH}")
64+
except RuntimeError:
65+
LOGGER.info(f"Could not open raster path {LULC_RASTER_PATH}")
6466
if _LULC_RASTER_INFO is None:
6567
raise AssertionError(
6668
f"Could not open {LULC_FILENAME} at any known locations")

docker-compose.yml

Lines changed: 85 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,103 @@
11
services:
2-
frontend:
3-
build: frontend
4-
command: yarn start-docker
5-
ports:
6-
- 3000:3000
7-
restart: on-failure
8-
volumes:
9-
- ./frontend/src:/opt/frontend/src
10-
- ./appdata:/opt/appdata
11-
- ./frontend/vite.config.js:/opt/frontend/vite.config.js
12-
- ./frontend/index.html:/opt/frontend/index.html
13-
secrets:
14-
- source: frontend-api-keys
15-
target: .env
2+
nginx-proxy-prod:
3+
build:
4+
context: nginx-proxy
5+
args:
6+
ENV: "prod"
7+
ports:
8+
- 80:80
9+
- 443:443
10+
depends_on:
11+
- frontend-prod
12+
- api
13+
- worker
14+
- fileserver-prod
15+
volumes:
16+
- ./certbot/www/:/var/www/certbot/
17+
- ./certbot/conf/:/etc/letsencrypt/
18+
profiles: [prod]
19+
nginx-proxy-dev:
20+
build:
21+
context: nginx-proxy
22+
args:
23+
ENV: "dev"
24+
ports:
25+
- 80:80
26+
depends_on:
27+
- frontend-dev
28+
- api
29+
- worker
30+
- fileserver-dev
31+
profiles: [dev]
32+
frontend-prod:
33+
build: frontend
34+
command: yarn start-docker-prod
35+
ports:
36+
- 3000:3000
37+
restart: on-failure
38+
volumes:
39+
- ./frontend/src:/opt/frontend/src
40+
- ./appdata:/opt/appdata
41+
- ./frontend/vite.config.js:/opt/frontend/vite.config.js
42+
- ./frontend/index.html:/opt/frontend/index.html
43+
secrets:
44+
- source: frontend-api-keys
45+
target: .env
46+
profiles: [prod]
47+
frontend-dev:
48+
build: frontend
49+
command: yarn start-docker-dev
50+
ports:
51+
- 3000:3000
52+
restart: on-failure
53+
volumes:
54+
- ./frontend/src:/opt/frontend/src
55+
- ./appdata:/opt/appdata
56+
- ./frontend/vite.config.js:/opt/frontend/vite.config.js
57+
- ./frontend/index.html:/opt/frontend/index.html
58+
secrets:
59+
- source: frontend-api-keys
60+
target: .env
61+
profiles: [dev]
1662
api:
1763
build: server
1864
ports:
19-
- 8000:8000
65+
- 8000:8000
2066
restart: on-failure
2167
volumes:
22-
- ./server:/opt/server
23-
- ./appdata:/opt/appdata
68+
- ./server:/opt/server
69+
- ./appdata:/opt/appdata
2470
worker:
2571
build: backend-worker
2672
command: /opt/conda/bin/python /opt/worker/worker.py api 8000 /opt/appdata
2773
restart: on-failure
2874
volumes:
29-
- ./backend-worker:/opt/worker
30-
- ./appdata:/opt/appdata
31-
fileserver:
75+
- ./backend-worker:/opt/worker
76+
- ./appdata:/opt/appdata
77+
fileserver-prod:
78+
image: nginx:mainline
79+
restart: on-failure
80+
ports:
81+
- 9000:9000
82+
volumes:
83+
- ./fileserver/app-prod.conf:/etc/nginx/conf.d/default.conf
84+
- ./appdata:/opt/appdata
85+
profiles: [prod]
86+
fileserver-dev:
3287
image: nginx:mainline
3388
restart: on-failure
3489
ports:
35-
- 9000:80
90+
- 9000:9000
3691
volumes:
37-
- ./fileserver/app.conf:/etc/nginx/conf.d/default.conf
38-
- ./appdata:/opt/appdata
92+
- ./fileserver/app-dev.conf:/etc/nginx/conf.d/default.conf
93+
- ./appdata:/opt/appdata
94+
profiles: [dev]
95+
certbot:
96+
image: certbot/certbot:latest
97+
volumes:
98+
- ./certbot/www/:/var/www/certbot/:rw
99+
- ./certbot/conf/:/etc/letsencrypt/:rw
100+
profiles: [prod]
39101

40102
secrets:
41103
frontend-api-keys:
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
# /etc/nginx/conf.d/default.conf
33

44
server {
5+
listen 9000;
56
location / {
67
root /opt/appdata;
78
autoindex on;
89
autoindex_format html;
910

1011
# CORS stuff adapted from https://enable-cors.org/server_nginx.html
1112
if ($request_method = 'OPTIONS') {
12-
add_header 'Access-Control-Allow-Origin' 'http://localhost:3000';
13+
add_header 'Access-Control-Allow-Origin' 'http://localhost' always;
1314
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
1415
#
1516
# Custom headers and headers various browsers *should* be OK with but aren't
@@ -24,13 +25,13 @@ server {
2425
return 204;
2526
}
2627
if ($request_method = 'POST') {
27-
add_header 'Access-Control-Allow-Origin' 'http://localhost:3000' always;
28+
add_header 'Access-Control-Allow-Origin' 'http://localhost' always;
2829
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
2930
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
3031
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
3132
}
3233
if ($request_method = 'GET') {
33-
add_header 'Access-Control-Allow-Origin' 'http://localhost:3000' always;
34+
add_header 'Access-Control-Allow-Origin' 'http://localhost' always;
3435
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
3536
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
3637
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;

fileserver/app-prod.conf

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# This file is intended to overwrite the default bonus config file at
2+
# /etc/nginx/conf.d/default.conf
3+
4+
server {
5+
listen 9000;
6+
location / {
7+
root /opt/appdata;
8+
autoindex on;
9+
autoindex_format html;
10+
11+
# CORS stuff adapted from https://enable-cors.org/server_nginx.html
12+
if ($request_method = 'OPTIONS') {
13+
add_header 'Access-Control-Allow-Origin' 'https://urbanonline.naturalcapitalproject.org' always;
14+
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
15+
#
16+
# Custom headers and headers various browsers *should* be OK with but aren't
17+
#
18+
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
19+
#
20+
# Tell client that this pre-flight info is valid for 20 days
21+
#
22+
add_header 'Access-Control-Max-Age' 1728000;
23+
add_header 'Content-Type' 'text/plain; charset=utf-8';
24+
add_header 'Content-Length' 0;
25+
return 204;
26+
}
27+
if ($request_method = 'POST') {
28+
add_header 'Access-Control-Allow-Origin' 'https://urbanonline.naturalcapitalproject.org' always;
29+
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
30+
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
31+
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
32+
}
33+
if ($request_method = 'GET') {
34+
add_header 'Access-Control-Allow-Origin' 'https://urbanonline.naturalcapitalproject.org' always;
35+
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
36+
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
37+
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
38+
}
39+
}
40+
}

frontend/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ RUN mkdir /opt/frontend
55
WORKDIR /opt/frontend
66

77
ADD ./package.json /opt/frontend/
8+
RUN yarn add puppeteer --ignore-scripts
89
RUN yarn install --production=false
10+
#RUN yarn cache clean && yarn install --production=false
911

1012
EXPOSE 3000
1113

12-
CMD yarn start-docker
14+
CMD yarn start-docker-dev

frontend/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"version": "0.0.0",
55
"scripts": {
66
"start": "vite",
7-
"start-docker": "cross-env MODE=docker vite --host 0.0.0.0 --port 3000",
7+
"start-docker-prod": "cross-env MODE=docker VITE_URBANONLINE_DEVMODE=false vite --host 0.0.0.0 --port 3000",
8+
"start-docker-dev": "cross-env MODE=docker VITE_URBANONLINE_DEVMODE=true vite --host 0.0.0.0 --port 3000",
89
"build": "vite build",
910
"serve": "vite preview",
1011
"test": "vitest run --dir tests --coverage",

frontend/src/requests.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import patternsTable from './edit/patternsTable'; // TODO: this is temp
2-
3-
const apiBaseURL = 'http://127.0.0.1:8000';
2+
3+
let apiBaseURL;
4+
if (import.meta.env.VITE_URBANONLINE_DEVMODE === 'true') {
5+
apiBaseURL = 'http://localhost/8000';
6+
}
7+
else {
8+
apiBaseURL = 'https://urbanonline.naturalcapitalproject.org/8000';
9+
}
410

511

612
/**

0 commit comments

Comments
 (0)