Skip to content

Commit ee1ffd9

Browse files
committed
nginx deployment
1 parent b31aa9e commit ee1ffd9

File tree

4 files changed

+200
-8
lines changed

4 files changed

+200
-8
lines changed

Dockerfile

+2-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
2222

2323
COPY ./src/app /code/app
2424

25+
# -------- replace with comment to run with gunicorn --------
2526
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
26-
27-
# to run with gunicorn and 4 workers use the following:
28-
# CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker". "-b", "0.0.0.0:8000"]
27+
# CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker". "-b", "0.0.0.0:8000"]

README.md

+156-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
<a href="https://docs.docker.com/compose/">
2929
<img src="https://img.shields.io/badge/Docker-2496ED?logo=docker&logoColor=fff&style=for-the-badge" alt="Docker">
3030
</a>
31+
<a href="https://nginx.org/en/">
32+
<img src="https://img.shields.io/badge/NGINX-009639?logo=nginx&logoColor=fff&style=flat" alt=NGINX>
33+
</a>
3134
</p>
3235

3336
## 0. About
@@ -39,6 +42,7 @@
3942
- [`Redis`](https://redis.io): Open source, in-memory data store used by millions as a cache, message broker and more.
4043
- [`ARQ`](https://arq-docs.helpmanual.io) Job queues and RPC in python with asyncio and redis.
4144
- [`Docker Compose`](https://docs.docker.com/compose/) With a single command, create and start all the services from your configuration.
45+
- [`NGINX`](https://nginx.org/en/) High-performance low resource consumption web server used for Reverse Proxy and Load Balancing.
4246

4347
## 1. Features
4448
- ⚡️ Fully async
@@ -47,13 +51,14 @@
4751
- 🏬 Easy redis caching
4852
- 👜 Easy client-side caching
4953
- 🚦 ARQ integration for task queue
50-
- ⚙️ Efficient querying (only queries what's needed)
54+
- ⚙️ Efficient querying (only queries what's needed) with support for joins
5155
- ⎘ Out of the box pagination support
5256
- 🛑 Rate Limiter dependency
5357
- 👮 FastAPI docs behind authentication and hidden based on the environment
5458
- 🦾 Easily extendable
5559
- 🤸‍♂️ Flexible
5660
- 🚚 Easy running with docker compose
61+
- ⚖️ NGINX Reverse Proxy and Load Balancing
5762

5863
## 2. Contents
5964
0. [About](#0-about)
@@ -82,12 +87,17 @@
8287
6. [CRUD](#56-crud)
8388
7. [Routes](#57-routes)
8489
1. [Paginated Responses](#571-paginated-responses)
90+
2. [HTTP Exceptions](#572-http-exceptions)
8591
8. [Caching](#58-caching)
8692
9. [More Advanced Caching](#59-more-advanced-caching)
8793
10. [ARQ Job Queues](#510-arq-job-queues)
8894
11. [Rate Limiting](#511-rate-limiting)
8995
12. [Running](#512-running)
9096
6. [Running in Production](#6-running-in-production)
97+
1. [Uvicorn Workers with Gunicorn](#61-uvicorn-workers-with-gunicorn)
98+
2. [Running With NGINX](#62-running-with-nginx)
99+
1. [One Server](#621-one-server)
100+
2. [Multiple Servers](#622-multiple-servers)
91101
7. [Testing](#7-testing)
92102
8. [Contributing](#8-contributing)
93103
9. [References](#9-references)
@@ -178,7 +188,7 @@ For ARQ Job Queues:
178188
REDIS_CACHE_HOST="your_host" # default "localhost", if using docker compose you should use "db"
179189
REDIS_CACHE_PORT=6379
180190
```
181-
> **Warning**
191+
> [!WARNING]
182192
> You may use the same redis for both caching and queue while developing, but the recommendation is using two separate containers for production.
183193
184194
To create the first tier:
@@ -1261,31 +1271,172 @@ poetry run arq app.worker.WorkerSettings
12611271
```
12621272

12631273
## 6. Running in Production
1264-
In production you probably should run using gunicorn workers:
1274+
### 6.1 Uvicorn Workers with Gunicorn
1275+
In production you may want to run using gunicorn to manage uvicorn workers:
12651276
```sh
12661277
command: gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
12671278
```
12681279
Here it's running with 4 workers, but you should test it depending on how many cores your machine has.
12691280

12701281
To do this if you are using docker compose, just replace the comment:
1271-
This part in docker-compose.yml:
1282+
This part in `docker-compose.yml`:
12721283
```python
1284+
# docker-compose.yml
1285+
12731286
# -------- replace with comment to run with gunicorn --------
12741287
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
12751288
# command: gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
12761289
```
12771290

12781291
Should be changed to:
12791292
```python
1293+
# docker-compose.yml
1294+
12801295
# -------- replace with comment to run with uvicorn --------
12811296
# command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
12821297
command: gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
12831298
```
12841299

1300+
And the same in `Dockerfile`:
1301+
This part:
1302+
```python
1303+
# Dockerfile
1304+
1305+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
1306+
# CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker". "-b", "0.0.0.0:8000"]
1307+
```
1308+
1309+
Should be changed to:
1310+
```python
1311+
# Dockerfile
1312+
1313+
# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
1314+
CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker". "-b", "0.0.0.0:8000"]
1315+
```
1316+
12851317
> [!CAUTION]
12861318
> Do not forget to set the `ENVIRONMENT` in `.env` to `production` unless you want the API docs to be public.
12871319
1288-
More on running it in production later.
1320+
### 6.2 Running with NGINX
1321+
NGINX is a high-performance web server, known for its stability, rich feature set, simple configuration, and low resource consumption. NGINX acts as a reverse proxy, that is, it receives client requests, forwards them to the FastAPI server (running via Uvicorn or Gunicorn), and then passes the responses back to the clients.
1322+
1323+
To run with NGINX, you start by uncommenting the following part in your `docker-compose.yml`:
1324+
```python
1325+
# docker-compose.yml
1326+
1327+
...
1328+
# #-------- uncomment to run with nginx --------
1329+
# nginx:
1330+
# image: nginx:latest
1331+
# ports:
1332+
# - "80:80"
1333+
# volumes:
1334+
# - ./default.conf:/etc/nginx/conf.d/default.conf
1335+
# depends_on:
1336+
# - web
1337+
...
1338+
```
1339+
1340+
Which should be changed to:
1341+
```python
1342+
# docker-compose.yml
1343+
1344+
...
1345+
#-------- uncomment to run with nginx --------
1346+
nginx:
1347+
image: nginx:latest
1348+
ports:
1349+
- "80:80"
1350+
volumes:
1351+
- ./default.conf:/etc/nginx/conf.d/default.conf
1352+
depends_on:
1353+
- web
1354+
...
1355+
```
1356+
1357+
Then comment the following part:
1358+
```python
1359+
# docker-compose.yml
1360+
1361+
services:
1362+
web:
1363+
...
1364+
# -------- Both of the following should be commented to run with nginx --------
1365+
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
1366+
# command: gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
1367+
```
1368+
1369+
Which becomes:
1370+
```python
1371+
# docker-compose.yml
1372+
1373+
services:
1374+
web:
1375+
...
1376+
# -------- Both of the following should be commented to run with nginx --------
1377+
# command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
1378+
# command: gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
1379+
```
1380+
1381+
Then pick the way you want to run (uvicorn or gunicorn managing uvicorn workers) in `Dockerfile`.
1382+
The one you want should be uncommented, comment the other one.
1383+
```python
1384+
# Dockerfile
1385+
1386+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
1387+
# CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker". "-b", "0.0.0.0:8000"]
1388+
```
1389+
1390+
#### 6.2.1 One Server
1391+
If you want to run with one server only, your setup should be ready. Just make sure the only part that is not a comment in `deafult.conf` is:
1392+
```python
1393+
# default.conf
1394+
1395+
# ---------------- Running With One Server ----------------
1396+
server {
1397+
listen 80;
1398+
1399+
location / {
1400+
proxy_pass http://web:8000;
1401+
proxy_set_header Host $host;
1402+
proxy_set_header X-Real-IP $remote_addr;
1403+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
1404+
proxy_set_header X-Forwarded-Proto $scheme;
1405+
}
1406+
}
1407+
```
1408+
1409+
#### 6.2.2 Multiple Servers
1410+
NGINX can distribute incoming network traffic across multiple servers, improving the efficiency and capacity utilization of your application.
1411+
1412+
To run with multiple servers, just comment the `Running With One Server` part in `default.conf` and Uncomment the other one:
1413+
```python
1414+
# default.conf
1415+
1416+
# ---------------- Running With One Server ----------------
1417+
...
1418+
1419+
# ---------------- To Run with Multiple Servers, Uncomment below ----------------
1420+
upstream fastapi_app {
1421+
server fastapi1:8000; # Replace with actual server names or IP addresses
1422+
server fastapi2:8000;
1423+
# Add more servers as needed
1424+
}
1425+
1426+
server {
1427+
listen 80;
1428+
1429+
location / {
1430+
proxy_pass http://fastapi_app;
1431+
proxy_set_header Host $host;
1432+
proxy_set_header X-Real-IP $remote_addr;
1433+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
1434+
proxy_set_header X-Forwarded-Proto $scheme;
1435+
}
1436+
}
1437+
```
1438+
> [!WARNING]
1439+
> Note that we are using `fastapi1:8000` and `fastapi2:8000` as examples, you should replace it with the actual name of your service and the port it's running on.
12891440
12901441
## 7. Testing
12911442
For tests, ensure you have in `.env`:

default.conf

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# ---------------- Running With One Server ----------------
2+
server {
3+
listen 80;
4+
5+
location / {
6+
proxy_pass http://web:8000;
7+
proxy_set_header Host $host;
8+
proxy_set_header X-Real-IP $remote_addr;
9+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
10+
proxy_set_header X-Forwarded-Proto $scheme;
11+
}
12+
}
13+
14+
15+
# # ---------------- To Run with Multiple Servers, Uncomment below ----------------
16+
# upstream fastapi_app {
17+
# server fastapi1:8000; # Replace with actual server names or IP addresses
18+
# server fastapi2:8000;
19+
# # Add more servers as needed
20+
# }
21+
22+
# server {
23+
# listen 80;
24+
25+
# location / {
26+
# proxy_pass http://fastapi_app;
27+
# proxy_set_header Host $host;
28+
# proxy_set_header X-Real-IP $remote_addr;
29+
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
30+
# proxy_set_header X-Forwarded-Proto $scheme;
31+
# }
32+
# }

docker-compose.yml

+10
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ services:
4545
volumes:
4646
- redis-data:/data
4747

48+
# #-------- uncomment to run with nginx --------
49+
# nginx:
50+
# image: nginx:latest
51+
# ports:
52+
# - "80:80"
53+
# volumes:
54+
# - ./default.conf:/etc/nginx/conf.d/default.conf
55+
# depends_on:
56+
# - web
57+
4858
# #-------- uncomment to create first superuser --------
4959
# create_superuser:
5060
# build:

0 commit comments

Comments
 (0)