├── .gitignore
├── .vscode
├── launch.json
└── settings.json
├── README.md
├── app
├── .dockerignore
├── Dockerfile
├── app
│ └── main.py
└── requirements.txt
├── develop.sh
├── docker-compose.yml
└── ui
├── .dockerignore
├── .gitignore
├── Dockerfile
├── README.md
├── nginx
└── nginx.conf
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
├── serviceWorker.js
└── setupTests.js
/.gitignore:
--------------------------------------------------------------------------------
1 | virtual
2 | /ui/node_modules
3 | /ui/yarn.lock
4 | /app/app/__pycache__
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Python: Current File",
9 | "type": "python",
10 | "request": "launch",
11 | "program": "${file}",
12 | "console": "integratedTerminal"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.pythonPath": "virtual/bin/python3.7"
3 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## FastAPI + React + Docker + Nginx
2 |
3 | ### Getting Started
4 | 1. Clone the repo and cd the directory.
5 | 2. Set up the virtual env for python backend - `virtualenv virtual`
6 | 3. Activate virtualenv `. virtual/bin/activate` and install dependencies - `pip install -r app/requirements.txt`. Once installed, you can deactivate virtualenv.
7 | 4. Install ui dependencies - `yarn --cwd ./ui `. `--cwd ./ui` allows to specify directory where package.json is located.
8 | 5. You are all set up. Now run `./develop.sh` and you have live development environment. Make changes to app or ui code and it will hot-reload.
--------------------------------------------------------------------------------
/app/.dockerignore:
--------------------------------------------------------------------------------
1 | /virtual
2 | /app/__pycache__
--------------------------------------------------------------------------------
/app/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
2 |
3 | COPY ./app /app
4 |
5 | ENV PORT=8080
--------------------------------------------------------------------------------
/app/app/main.py:
--------------------------------------------------------------------------------
1 | import uvicorn
2 | from fastapi import FastAPI
3 | from pydantic import BaseModel
4 | from typing import List
5 |
6 | app = FastAPI()
7 |
8 | class Item(BaseModel):
9 | name: str
10 | price: float
11 | is_offer: bool = None
12 |
13 |
14 | class Result(BaseModel):
15 | code: int = 0
16 | message: str = ''
17 | items: List[Item] = None
18 |
19 |
20 | class User(BaseModel):
21 | username: str
22 | hostname: str
23 |
24 |
25 | @app.get("/api/user", response_model=User)
26 | def read_user():
27 | import socket
28 | import getpass
29 | return {
30 | "username": getpass.getuser(),
31 | "hostname": socket.gethostname()
32 | }
33 |
34 | @app.get("/api/")
35 | def read_root():
36 | return {"Hello": "World"}
37 |
38 |
39 | @app.get("/api/items/{item_id}", response_model=Result)
40 | def read_item(item_id: int, q: str = None):
41 | return {"item_id": item_id, "q": q}
42 |
43 |
44 | @app.put("/api/items/{item_id}")
45 | def update_item(item_id: int, item: Item):
46 | return {"item_name": item.name, "item_id": item_id}
47 |
48 |
49 | if __name__ == "__main__":
50 | uvicorn.run("main:app", port=8000, reload=True)
--------------------------------------------------------------------------------
/app/requirements.txt:
--------------------------------------------------------------------------------
1 | fastapi
2 | uvicorn
--------------------------------------------------------------------------------
/develop.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | ./virtual/bin/python3.7 ./app/app/main.py & yarn --cwd ./ui start
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.7'
2 | services:
3 | docker-fastapi:
4 | container_name: docker-fastapi
5 | build:
6 | context: ./app/
7 | dockerfile: Dockerfile
8 | restart: always
9 | nginx:
10 | depends_on:
11 | - docker-fastapi
12 | container_name: proxy-app
13 | build:
14 | context: ./ui/
15 | dockerfile: Dockerfile
16 | ports:
17 | - "80:80"
18 | restart: always
19 |
--------------------------------------------------------------------------------
/ui/.dockerignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | yarn.lock
--------------------------------------------------------------------------------
/ui/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/ui/Dockerfile:
--------------------------------------------------------------------------------
1 | # set the base image
2 | # n/b: for production, node is only used for building
3 | # the static Html and javascript files
4 | # as react creates static html and js files after build
5 | # these are what will be served by nginx
6 | # use alias build to be easier to refer this container elsewhere
7 | # e.g inside nginx container
8 | FROM node:alpine as build
9 | # set working directory
10 | # this is the working folder in the container
11 | # from which the app will be running from
12 | WORKDIR /app
13 | # copy everything to /app directory
14 | # as opposed to on dev, in prod everything is copied to docker
15 | COPY . /app
16 | # add the node_modules folder to $PATH
17 | # ENV PATH /app/node_modules/.bin:$PATH
18 | # install and cache dependencies
19 | RUN yarn
20 | #build the project for production
21 | RUN yarn build
22 | # set up production environment
23 | # the base image for this is an alpine based nginx image
24 | FROM nginx:alpine
25 | # copy the build folder from react to the root of nginx (www)
26 | COPY --from=build /app/build /usr/share/nginx/html
27 | # --------- only for those using react router ----------
28 | # if you are using react router
29 | # you need to overwrite the default nginx configurations
30 | # remove default nginx configuration file
31 | RUN rm /etc/nginx/conf.d/default.conf
32 | # replace with custom one
33 | COPY nginx/nginx.conf /etc/nginx/conf.d
34 | # --------- /only for those using react router ----------
35 | # expose port 80 to the outer world
36 | EXPOSE 80
37 | # start nginx
38 | CMD ["nginx", "-g", "daemon off;"]
--------------------------------------------------------------------------------
/ui/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `yarn start`
8 |
9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
11 |
12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console.
14 |
15 | ### `yarn test`
16 |
17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
19 |
20 | ### `yarn build`
21 |
22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance.
24 |
25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed!
27 |
28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
29 |
30 | ### `yarn eject`
31 |
32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
33 |
34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
35 |
36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
37 |
38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
39 |
40 | ## Learn More
41 |
42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
43 |
44 | To learn React, check out the [React documentation](https://reactjs.org/).
45 |
46 | ### Code Splitting
47 |
48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
49 |
50 | ### Analyzing the Bundle Size
51 |
52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
53 |
54 | ### Making a Progressive Web App
55 |
56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
57 |
58 | ### Advanced Configuration
59 |
60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
61 |
62 | ### Deployment
63 |
64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
65 |
66 | ### `yarn build` fails to minify
67 |
68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
69 |
--------------------------------------------------------------------------------
/ui/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | upstream docker_fastapi {
2 | server docker-fastapi:8080;
3 | }
4 |
5 | server {
6 | listen 80;
7 |
8 | location ~ /api/ {
9 | proxy_pass http://docker_fastapi;
10 | proxy_set_header Host $host;
11 | proxy_set_header X-Real-IP $remote_addr;
12 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
13 | proxy_set_header X-Forwarded-Host $server_name;
14 | }
15 |
16 | location / {
17 | root /usr/share/nginx/html;
18 | index index.html index.htm;
19 | try_files $uri $uri/ /index.html;
20 | }
21 |
22 | error_page 500 502 503 504 /50x.html;
23 |
24 | location = /50x.html {
25 | root /usr/share/nginx/html;
26 | }
27 | }
--------------------------------------------------------------------------------
/ui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ui",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^4.2.4",
7 | "@testing-library/react": "^9.3.2",
8 | "@testing-library/user-event": "^7.1.2",
9 | "react": "^16.12.0",
10 | "react-dom": "^16.12.0",
11 | "react-scripts": "3.3.0"
12 | },
13 | "scripts": {
14 | "start": "react-scripts start",
15 | "build": "react-scripts build",
16 | "test": "react-scripts test",
17 | "eject": "react-scripts eject"
18 | },
19 | "eslintConfig": {
20 | "extends": "react-app"
21 | },
22 | "browserslist": {
23 | "production": [
24 | ">0.2%",
25 | "not dead",
26 | "not op_mini all"
27 | ],
28 | "development": [
29 | "last 1 chrome version",
30 | "last 1 firefox version",
31 | "last 1 safari version"
32 | ]
33 | },
34 | "proxy": "http://localhost:8000",
35 | "devDependencies": {}
36 | }
--------------------------------------------------------------------------------
/ui/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vikramgulia/fastapi-react/b48d19b36c0668d774a61ed1b35af92a1b8d8e53/ui/public/favicon.ico
--------------------------------------------------------------------------------
/ui/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
26 | Edit src/App.js
and save to reload.
27 |
Hostname : {host}
38 |