├── precip_service
├── requirements.txt
├── Dockerfile
└── precip_server.py
├── temperature_service
├── requirements.txt
├── Dockerfile
└── temperature_server.py
├── .vscode
└── settings.json
├── reverse proxy.png
├── weather_report
├── babel.config.js
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── assets
│ │ └── logo.png
│ ├── main.js
│ ├── App.vue
│ └── components
│ │ └── HelloWorld.vue
├── Dockerfile
├── .gitignore
├── README.md
├── nginx.conf
└── package.json
├── README.md
├── reverse_proxy
└── nginx.conf
├── docker-compose.yml
└── LICENSE
/precip_service/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==1.1.2
--------------------------------------------------------------------------------
/temperature_service/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==1.1.2
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.fontSize": 16
3 | }
--------------------------------------------------------------------------------
/reverse proxy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/productive-dev/minimal-reverse-proxy-demo/HEAD/reverse proxy.png
--------------------------------------------------------------------------------
/weather_report/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/weather_report/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/productive-dev/minimal-reverse-proxy-demo/HEAD/weather_report/public/favicon.ico
--------------------------------------------------------------------------------
/weather_report/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/productive-dev/minimal-reverse-proxy-demo/HEAD/weather_report/src/assets/logo.png
--------------------------------------------------------------------------------
/weather_report/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 |
4 | Vue.config.productionTip = false
5 |
6 | new Vue({
7 | render: h => h(App),
8 | }).$mount('#app')
9 |
--------------------------------------------------------------------------------
/precip_service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.7-alpine
2 |
3 | WORKDIR /app
4 |
5 | COPY requirements.txt .
6 |
7 | RUN pip install -r requirements.txt
8 |
9 | COPY . .
10 |
11 | EXPOSE 5002
12 |
13 | CMD ["python", "precip_server.py"]
--------------------------------------------------------------------------------
/temperature_service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.7-alpine
2 |
3 | WORKDIR /app
4 |
5 | COPY requirements.txt .
6 |
7 | RUN pip install -r requirements.txt
8 |
9 | COPY . .
10 |
11 | EXPOSE 5001
12 |
13 | CMD ["python", "temperature_server.py"]
--------------------------------------------------------------------------------
/weather_report/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:latest as build-stage
2 | WORKDIR /app
3 | COPY package*.json ./
4 | RUN npm install
5 | COPY ./ .
6 | RUN npm run build
7 |
8 | FROM nginx:latest as production-stage
9 | RUN mkdir /app
10 | COPY --from=build-stage /app/dist /app
11 | COPY nginx.conf /etc/nginx/nginx.conf
--------------------------------------------------------------------------------
/weather_report/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/temperature_service/temperature_server.py:
--------------------------------------------------------------------------------
1 | import random
2 | from flask import Flask
3 |
4 | app = Flask(__name__)
5 |
6 | @app.route('/')
7 | def get_temperature():
8 | temperature_c = random.randint(-10, 33)
9 | return { 'temperature_c': temperature_c }
10 |
11 | if __name__ == '__main__':
12 | app.run(host='0.0.0.0', port='5001')
--------------------------------------------------------------------------------
/weather_report/README.md:
--------------------------------------------------------------------------------
1 | # weather_report
2 |
3 | ## Project setup
4 | ```
5 | yarn install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | yarn serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | yarn build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | yarn lint
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Minimal nginx reverse proxy demo
2 |
3 | This repository contains a `docker-compose` orchestrated application with Flask and Vue services running behind an nginx reverse proxy.
4 |
5 | ## Warning
6 |
7 | This application and its services are not production ready, and is not propely configured for deployment. It serves only as a basic starting point to configure nginx and orchestrate several services with `docker-compose`.
8 |
9 | ## Running
10 |
11 | To build the containers:
12 | `docker-compose build`
13 |
14 | To run the containers:
15 | `docker-compose up`
16 |
17 | ## Oversimplified Diagram
18 |
19 |
--------------------------------------------------------------------------------
/weather_report/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 |
7 |
8 |
18 |
19 |
29 |
--------------------------------------------------------------------------------
/weather_report/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/precip_service/precip_server.py:
--------------------------------------------------------------------------------
1 | import random
2 | from flask import Flask, request
3 |
4 | app = Flask(__name__)
5 |
6 | @app.route('/')
7 | def get_precipitation():
8 |
9 | temperature_c = int(request.args.get('temp'))
10 |
11 | if not temperature_c:
12 | temperature_c = 23
13 |
14 | precip_type = "rain"
15 |
16 | is_cold = temperature_c < 0
17 | is_warm = temperature_c > 25
18 |
19 | if is_cold:
20 | print('cold weather detected')
21 | precip_type = "snow"
22 |
23 | if is_warm:
24 | print('warm weather detected')
25 | precip_type = "storms"
26 |
27 | percent_chance = round(random.uniform(0, 1) * 100)
28 |
29 | return {
30 | 'precip_chance': percent_chance,
31 | 'type': precip_type
32 | }
33 |
34 |
35 |
36 | if __name__ == '__main__':
37 | app.run(host='0.0.0.0', port='5002')
--------------------------------------------------------------------------------
/reverse_proxy/nginx.conf:
--------------------------------------------------------------------------------
1 | user www-data;
2 | worker_processes auto;
3 | pid /run/nginx.pid;
4 | include /etc/nginx/modules-enabled/*.conf;
5 |
6 | events {
7 | worker_connections 1024;
8 | }
9 |
10 | http {
11 | # Weather Report Reverse Proxy
12 | server {
13 | listen 80;
14 | server_name localhost 127.0.0.1;
15 |
16 | location / {
17 | proxy_pass http://weather-report:80;
18 | proxy_set_header X-Forwarded-For $remote_addr;
19 | }
20 |
21 | location /temperature {
22 | proxy_pass http://temperature-service:5001/;
23 | proxy_set_header X-Forwarded-For $remote_addr;
24 | }
25 |
26 | location /precipitation {
27 | proxy_pass http://precip-service:5002/;
28 | proxy_set_header X-Forwarded-For $remote_addr;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/weather_report/nginx.conf:
--------------------------------------------------------------------------------
1 | user nginx;
2 | worker_processes 1;
3 | error_log /var/log/nginx/error.log warn;
4 | pid /var/run/nginx.pid;
5 |
6 | events {
7 | worker_connections 1024;
8 | }
9 |
10 | http {
11 | include /etc/nginx/mime.types;
12 | default_type application/octet-stream;
13 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
14 | '$status $body_bytes_sent "$http_referer" '
15 | '"$http_user_agent" "$http_x_forwarded_for"';
16 | access_log /var/log/nginx/access.log main;
17 | sendfile on;
18 | keepalive_timeout 65;
19 |
20 | server {
21 | listen 80;
22 | server_name localhost;
23 | root /app;
24 |
25 | location / {
26 | index index.html;
27 | try_files $uri $uri/ /index.html;
28 | }
29 |
30 | error_page 500 502 503 504 /50x.html;
31 |
32 | location = /50x.html {
33 | root /usr/share/nginx/html;
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/weather_report/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "weather_report",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "axios": "^0.21.1",
12 | "core-js": "^3.6.4",
13 | "vue": "^2.6.11"
14 | },
15 | "devDependencies": {
16 | "@vue/cli-plugin-babel": "^4.3.0",
17 | "@vue/cli-plugin-eslint": "^4.3.0",
18 | "@vue/cli-service": "^4.3.0",
19 | "babel-eslint": "^10.1.0",
20 | "eslint": "^6.7.2",
21 | "eslint-plugin-vue": "^6.2.2",
22 | "vue-template-compiler": "^2.6.11"
23 | },
24 | "eslintConfig": {
25 | "root": true,
26 | "env": {
27 | "node": true
28 | },
29 | "extends": [
30 | "plugin:vue/essential",
31 | "eslint:recommended"
32 | ],
33 | "parserOptions": {
34 | "parser": "babel-eslint"
35 | },
36 | "rules": {}
37 | },
38 | "browserslist": [
39 | "> 1%",
40 | "last 2 versions",
41 | "not dead"
42 | ]
43 | }
44 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | # Proxies requests to internal services
6 | reverse-proxy:
7 | image: nginx:1.17.10
8 | container_name: reverse_proxy_demo
9 | depends_on:
10 | - weather-report
11 | - temperature-service
12 | - precip-service
13 | volumes:
14 | - ./reverse_proxy/nginx.conf:/etc/nginx/nginx.conf
15 | ports:
16 | - 80:80
17 |
18 | # generates weather reports
19 | weather-report:
20 | image: weather-report
21 | container_name: weather-report
22 | build:
23 | context: ./weather_report
24 | depends_on:
25 | - temperature-service
26 | - precip-service
27 | ports:
28 | - 8080:80
29 | restart: on-failure
30 |
31 |
32 | # Retrieves the temperature
33 | temperature-service:
34 | image: temperature-service
35 | container_name: temperature-service
36 | build:
37 | context: ./temperature_service
38 | ports:
39 | - 5001:5001
40 | restart: on-failure
41 |
42 |
43 | # Generates a precipitation estimate
44 | precip-service:
45 | image: precip-service
46 | container_name: precip-service
47 | build:
48 | context: ./precip_service
49 | ports:
50 | - 5002:5002
51 | restart: on-failure
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/weather_report/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Weather Report
4 |
5 | The temperature will be: {{ temperature }}
6 | and the chance of {{ precip_type }} is {{ precip_chance }}!
7 |
8 |
9 |
10 |
11 |
45 |
46 |
47 |
63 |
--------------------------------------------------------------------------------