├── 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 | 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 | 10 | 11 | 45 | 46 | 47 | 63 | --------------------------------------------------------------------------------