Browse Source
* 📝 Add docs for sponsors * 📝 Add docs for deploying on Deta * 🍱 Add Deta docs screenshots * ♻️ Refactor and separate deployment docs * 📝 Update internal docs links to Deployment * 📝 Update links in Deta tutorial * 🍱 Update sponsors images * 🔧 Use sponsors data from YAML * 📝 Update sponsors in languages docs * ✨ Update docs generation scripts * ✅ Update README.md testing * 📝 Update main README * 🔧 Update fastapi-people action handling individual sponsors * ✏️ Fix typos in Deta tutorialpull/2102/head
committed by
GitHub
34 changed files with 1236 additions and 415 deletions
@ -0,0 +1,8 @@ |
|||
gold: |
|||
- url: https://www.deta.sh/?ref=fastapi |
|||
title: The launchpad for all your (team's) ideas |
|||
img: /img/sponsors/deta.svg |
|||
silver: |
|||
- url: https://testdriven.io/ |
|||
title: Learn to build high-quality web apps with best practices |
|||
img: /img/sponsors/testdriven.svg |
@ -1,396 +0,0 @@ |
|||
# Deployment |
|||
|
|||
Deploying a **FastAPI** application is relatively easy. |
|||
|
|||
There are several ways to do it depending on your specific use case and the tools that you use. |
|||
|
|||
You will see more about some of the ways to do it in the next sections. |
|||
|
|||
## FastAPI versions |
|||
|
|||
**FastAPI** is already being used in production in many applications and systems. And the test coverage is kept at 100%. But its development is still moving quickly. |
|||
|
|||
New features are added frequently, bugs are fixed regularly, and the code is still continuously improving. |
|||
|
|||
That's why the current versions are still `0.x.x`, this reflects that each version could potentially have breaking changes. This follows the <a href="https://semver.org/" class="external-link" target="_blank">Semantic Versioning</a> conventions. |
|||
|
|||
You can create production applications with **FastAPI** right now (and you have probably been doing it for some time), you just have to make sure that you use a version that works correctly with the rest of your code. |
|||
|
|||
### Pin your `fastapi` version |
|||
|
|||
The first thing you should do is to "pin" the version of **FastAPI** you are using to the specific latest version that you know works correctly for your application. |
|||
|
|||
For example, let's say you are using version `0.45.0` in your app. |
|||
|
|||
If you use a `requirements.txt` file you could specify the version with: |
|||
|
|||
```txt |
|||
fastapi==0.45.0 |
|||
``` |
|||
|
|||
that would mean that you would use exactly the version `0.45.0`. |
|||
|
|||
Or you could also pin it with: |
|||
|
|||
```txt |
|||
fastapi>=0.45.0,<0.46.0 |
|||
``` |
|||
|
|||
that would mean that you would use the versions `0.45.0` or above, but less than `0.46.0`, for example, a version `0.45.2` would still be accepted. |
|||
|
|||
If you use any other tool to manage your installations, like Poetry, Pipenv, or others, they all have a way that you can use to define specific versions for your packages. |
|||
|
|||
### Available versions |
|||
|
|||
You can see the available versions (e.g. to check what is the current latest) in the [Release Notes](release-notes.md){.internal-link target=_blank}. |
|||
|
|||
### About versions |
|||
|
|||
Following the Semantic Versioning conventions, any version below `1.0.0` could potentially add breaking changes. |
|||
|
|||
FastAPI also follows the convention that any "PATCH" version change is for bug fixes and non-breaking changes. |
|||
|
|||
!!! tip |
|||
The "PATCH" is the last number, for example, in `0.2.3`, the PATCH version is `3`. |
|||
|
|||
So, you should be able to pin to a version like: |
|||
|
|||
```txt |
|||
fastapi>=0.45.0,<0.46.0 |
|||
``` |
|||
|
|||
Breaking changes and new features are added in "MINOR" versions. |
|||
|
|||
!!! tip |
|||
The "MINOR" is the number in the middle, for example, in `0.2.3`, the MINOR version is `2`. |
|||
|
|||
### Upgrading the FastAPI versions |
|||
|
|||
You should add tests for your app. |
|||
|
|||
With **FastAPI** it's very easy (thanks to Starlette), check the docs: [Testing](tutorial/testing.md){.internal-link target=_blank} |
|||
|
|||
After you have tests, then you can upgrade the **FastAPI** version to a more recent one, and make sure that all your code is working correctly by running your tests. |
|||
|
|||
If everything is working, or after you make the necessary changes, and all your tests are passing, then you can pin your `fastapi` to that new recent version. |
|||
|
|||
### About Starlette |
|||
|
|||
You shouldn't pin the version of `starlette`. |
|||
|
|||
Different versions of **FastAPI** will use a specific newer version of Starlette. |
|||
|
|||
So, you can just let **FastAPI** use the correct Starlette version. |
|||
|
|||
### About Pydantic |
|||
|
|||
Pydantic includes the tests for **FastAPI** with its own tests, so new versions of Pydantic (above `1.0.0`) are always compatible with FastAPI. |
|||
|
|||
You can pin Pydantic to any version above `1.0.0` that works for you and below `2.0.0`. |
|||
|
|||
For example: |
|||
|
|||
```txt |
|||
pydantic>=1.2.0,<2.0.0 |
|||
``` |
|||
|
|||
## Docker |
|||
|
|||
In this section you'll see instructions and links to guides to know how to: |
|||
|
|||
* Make your **FastAPI** application a Docker image/container with maximum performance. In about **5 min**. |
|||
* (Optionally) understand what you, as a developer, need to know about HTTPS. |
|||
* Set up a Docker Swarm mode cluster with automatic HTTPS, even on a simple $5 USD/month server. In about **20 min**. |
|||
* Generate and deploy a full **FastAPI** application, using your Docker Swarm cluster, with HTTPS, etc. In about **10 min**. |
|||
|
|||
You can use <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a> for deployment. It has several advantages like security, replicability, development simplicity, etc. |
|||
|
|||
If you are using Docker, you can use the official Docker image: |
|||
|
|||
### <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a> |
|||
|
|||
This image has an "auto-tuning" mechanism included, so that you can just add your code and get very high performance automatically. And without making sacrifices. |
|||
|
|||
But you can still change and update all the configurations with environment variables or configuration files. |
|||
|
|||
!!! tip |
|||
To see all the configurations and options, go to the Docker image page: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. |
|||
|
|||
### Create a `Dockerfile` |
|||
|
|||
* Go to your project directory. |
|||
* Create a `Dockerfile` with: |
|||
|
|||
```Dockerfile |
|||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7 |
|||
|
|||
COPY ./app /app |
|||
``` |
|||
|
|||
#### Bigger Applications |
|||
|
|||
If you followed the section about creating [Bigger Applications with Multiple Files](tutorial/bigger-applications.md){.internal-link target=_blank}, your `Dockerfile` might instead look like: |
|||
|
|||
```Dockerfile |
|||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7 |
|||
|
|||
COPY ./app /app/app |
|||
``` |
|||
|
|||
#### Raspberry Pi and other architectures |
|||
|
|||
If you are running Docker in a Raspberry Pi (that has an ARM processor) or any other architecture, you can create a `Dockerfile` from scratch, based on a Python base image (that is multi-architecture) and use Uvicorn alone. |
|||
|
|||
In this case, your `Dockerfile` could look like: |
|||
|
|||
```Dockerfile |
|||
FROM python:3.7 |
|||
|
|||
RUN pip install fastapi uvicorn |
|||
|
|||
EXPOSE 80 |
|||
|
|||
COPY ./app /app |
|||
|
|||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] |
|||
``` |
|||
|
|||
### Create the **FastAPI** Code |
|||
|
|||
* Create an `app` directory and enter in it. |
|||
* Create a `main.py` file with: |
|||
|
|||
```Python |
|||
from typing import Optional |
|||
|
|||
from fastapi import FastAPI |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/") |
|||
def read_root(): |
|||
return {"Hello": "World"} |
|||
|
|||
|
|||
@app.get("/items/{item_id}") |
|||
def read_item(item_id: int, q: Optional[str] = None): |
|||
return {"item_id": item_id, "q": q} |
|||
``` |
|||
|
|||
* You should now have a directory structure like: |
|||
|
|||
``` |
|||
. |
|||
├── app |
|||
│ └── main.py |
|||
└── Dockerfile |
|||
``` |
|||
|
|||
### Build the Docker image |
|||
|
|||
* Go to the project directory (in where your `Dockerfile` is, containing your `app` directory). |
|||
* Build your FastAPI image: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ docker build -t myimage . |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
### Start the Docker container |
|||
|
|||
* Run a container based on your image: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ docker run -d --name mycontainer -p 80:80 myimage |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
Now you have an optimized FastAPI server in a Docker container. Auto-tuned for your current server (and number of CPU cores). |
|||
|
|||
### Check it |
|||
|
|||
You should be able to check it in your Docker container's URL, for example: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> or <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (or equivalent, using your Docker host). |
|||
|
|||
You will see something like: |
|||
|
|||
```JSON |
|||
{"item_id": 5, "q": "somequery"} |
|||
``` |
|||
|
|||
### Interactive API docs |
|||
|
|||
Now you can go to <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> or <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (or equivalent, using your Docker host). |
|||
|
|||
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>): |
|||
|
|||
 |
|||
|
|||
### Alternative API docs |
|||
|
|||
And you can also go to <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> or <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (or equivalent, using your Docker host). |
|||
|
|||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>): |
|||
|
|||
 |
|||
|
|||
## HTTPS |
|||
|
|||
### About HTTPS |
|||
|
|||
It is easy to assume that HTTPS is something that is just "enabled" or not. |
|||
|
|||
But it is way more complex than that. |
|||
|
|||
!!! tip |
|||
If you are in a hurry or don't care, continue with the next section for step by step instructions to set everything up. |
|||
|
|||
To learn the basics of HTTPS, from a consumer perspective, check <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>. |
|||
|
|||
Now, from a developer's perspective, here are several things to have in mind while thinking about HTTPS: |
|||
|
|||
* For HTTPS, the server needs to have "certificates" generated by a third party. |
|||
* Those certificates are actually acquired from the third-party, not "generated". |
|||
* Certificates have a lifetime. |
|||
* They expire. |
|||
* And then they need to be renewed, acquired again from the third party. |
|||
* The encryption of the connection happens at the TCP level. |
|||
* That's one layer below HTTP. |
|||
* So, the certificate and encryption handling is done before HTTP. |
|||
* TCP doesn't know about "domains". Only about IP addresses. |
|||
* The information about the specific domain requested goes in the HTTP data. |
|||
* The HTTPS certificates "certify" a certain domain, but the protocol and encryption happen at the TCP level, before knowing which domain is being dealt with. |
|||
* By default, that would mean that you can only have one HTTPS certificate per IP address. |
|||
* No matter how big your server is or how small each application you have on it might be. |
|||
* There is a solution to this, however. |
|||
* There's an extension to the TLS protocol (the one handling the encryption at the TCP level, before HTTP) called <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication">SNI</abbr></a>. |
|||
* This SNI extension allows one single server (with a single IP address) to have several HTTPS certificates and serve multiple HTTPS domains/applications. |
|||
* For this to work, a single component (program) running on the server, listening on the public IP address, must have all the HTTPS certificates in the server. |
|||
* After obtaining a secure connection, the communication protocol is still HTTP. |
|||
* The contents are encrypted, even though they are being sent with the HTTP protocol. |
|||
|
|||
It is a common practice to have one program/HTTP server running on the server (the machine, host, etc.) and managing all the HTTPS parts : sending the decrypted HTTP requests to the actual HTTP application running in the same server (the **FastAPI** application, in this case), take the HTTP response from the application, encrypt it using the appropriate certificate and sending it back to the client using HTTPS. This server is often called a <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">TLS Termination Proxy</a>. |
|||
|
|||
### Let's Encrypt |
|||
|
|||
Before Let's Encrypt, these HTTPS certificates were sold by trusted third-parties. |
|||
|
|||
The process to acquire one of these certificates used to be cumbersome, require quite some paperwork and the certificates were quite expensive. |
|||
|
|||
But then <a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a> was created. |
|||
|
|||
It is a project from the Linux Foundation. It provides HTTPS certificates for free. In an automated way. These certificates use all the standard cryptographic security, and are short lived (about 3 months), so the security is actually better because of their reduced lifespan. |
|||
|
|||
The domains are securely verified and the certificates are generated automatically. This also allows automating the renewal of these certificates. |
|||
|
|||
The idea is to automate the acquisition and renewal of these certificates, so that you can have secure HTTPS, for free, forever. |
|||
|
|||
### Traefik |
|||
|
|||
<a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a> is a high performance reverse proxy / load balancer. It can do the "TLS Termination Proxy" job (apart from other features). |
|||
|
|||
It has integration with Let's Encrypt. So, it can handle all the HTTPS parts, including certificate acquisition and renewal. |
|||
|
|||
It also has integrations with Docker. So, you can declare your domains in each application configurations and have it read those configurations, generate the HTTPS certificates and serve HTTPS to your application automatically, without requiring any change in its configuration. |
|||
|
|||
--- |
|||
|
|||
With this information and tools, continue with the next section to combine everything. |
|||
|
|||
## Docker Swarm mode cluster with Traefik and HTTPS |
|||
|
|||
You can have a Docker Swarm mode cluster set up in minutes (about 20 min) with a main Traefik handling HTTPS (including certificate acquisition and renewal). |
|||
|
|||
By using Docker Swarm mode, you can start with a "cluster" of a single machine (it can even be a $5 USD / month server) and then you can grow as much as you need adding more servers. |
|||
|
|||
To set up a Docker Swarm Mode cluster with Traefik and HTTPS handling, follow this guide: |
|||
|
|||
### <a href="https://medium.com/@tiangolo/docker-swarm-mode-and-traefik-for-a-https-cluster-20328dba6232" class="external-link" target="_blank">Docker Swarm Mode and Traefik for an HTTPS cluster</a> |
|||
|
|||
### Deploy a FastAPI application |
|||
|
|||
The easiest way to set everything up, would be using the [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}. |
|||
|
|||
It is designed to be integrated with this Docker Swarm cluster with Traefik and HTTPS described above. |
|||
|
|||
You can generate a project in about 2 min. |
|||
|
|||
The generated project has instructions to deploy it, doing it takes another 2 min. |
|||
|
|||
## Alternatively, deploy **FastAPI** without Docker |
|||
|
|||
You can deploy **FastAPI** directly without Docker too. |
|||
|
|||
You just need to install an ASGI compatible server like: |
|||
|
|||
=== "Uvicorn" |
|||
|
|||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, a lightning-fast ASGI server, built on uvloop and httptools. |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install uvicorn |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
=== "Hypercorn" |
|||
|
|||
* <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, an ASGI server also compatible with HTTP/2. |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install hypercorn |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
...or any other ASGI server. |
|||
|
|||
And run your application the same way you have done in the tutorials, but without the `--reload` option, e.g.: |
|||
|
|||
=== "Uvicorn" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ uvicorn main:app --host 0.0.0.0 --port 80 |
|||
|
|||
<span style="color: green;">INFO</span>: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
=== "Hypercorn" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ hypercorn main:app --bind 0.0.0.0:80 |
|||
|
|||
Running on 0.0.0.0:8080 over http (CTRL + C to quit) |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
You might want to set up some tooling to make sure it is restarted automatically if it stops. |
|||
|
|||
You might also want to install <a href="https://gunicorn.org/" class="external-link" target="_blank">Gunicorn</a> and <a href="https://www.uvicorn.org/#running-with-gunicorn" class="external-link" target="_blank">use it as a manager for Uvicorn</a>, or use Hypercorn with multiple workers. |
|||
|
|||
Making sure to fine-tune the number of workers, etc. |
|||
|
|||
But if you are doing all that, you might just use the Docker image that does it automatically. |
@ -0,0 +1,240 @@ |
|||
# Deploy on Deta |
|||
|
|||
In this section you will learn see how to easily deploy a **FastAPI** application on <a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> using the free plan. 🎁 |
|||
|
|||
It will take you about **10 minutes**. |
|||
|
|||
!!! info |
|||
<a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> is a **FastAPI** sponsor. 🎉 |
|||
|
|||
## A basic **FastAPI** app |
|||
|
|||
* Create a directory for your app, for example `./fastapideta/` and enter in it. |
|||
|
|||
### FastAPI code |
|||
|
|||
* Create a `main.py` file with: |
|||
|
|||
```Python |
|||
from fastapi import FastAPI |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/") |
|||
def read_root(): |
|||
return {"Hello": "World"} |
|||
|
|||
|
|||
@app.get("/items/{item_id}") |
|||
def read_item(item_id: int): |
|||
return {"item_id": item_id} |
|||
``` |
|||
|
|||
### Requirements |
|||
|
|||
Now, in the same directory create a file `requirements.txt` with: |
|||
|
|||
```text |
|||
fastapi |
|||
``` |
|||
|
|||
!!! tip |
|||
You don't need to install Uvicorn to deploy on Deta, although you would probably want to install it locally to test your app. |
|||
|
|||
### Directory structure |
|||
|
|||
You will now have one directory `./fastapideta/` with two files: |
|||
|
|||
``` |
|||
. |
|||
└── main.py |
|||
└── requirements.txt |
|||
``` |
|||
|
|||
## Create a free Deta account |
|||
|
|||
Now create a <a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">free account on Deta</a>, you just need an email and password. |
|||
|
|||
You don't even need a credit card. |
|||
|
|||
## Install the CLI |
|||
|
|||
Once you have your account, install the Deta <abbr title="Command Line Interface application">CLI</abbr>: |
|||
|
|||
=== "Linux, macOS" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ curl -fsSL https://get.deta.dev/cli.sh | sh |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
=== "Windows PowerShell" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ iwr https://get.deta.dev/cli.ps1 -useb | iex |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
After installing it, open a new terminal so that the installed CLI is detected. |
|||
|
|||
In a new terminal, confirm that it was correctly installed with: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ deta --help |
|||
|
|||
Deta command line interface for managing deta micros. |
|||
Complete documentation available at https://docs.deta.sh |
|||
|
|||
Usage: |
|||
deta [flags] |
|||
deta [command] |
|||
|
|||
Available Commands: |
|||
auth Change auth settings for a deta micro |
|||
|
|||
... |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
!!! tip |
|||
If you have problems installing the CLI, check the <a href="https://docs.deta.sh/docs/micros/getting_started?ref=fastapi" class="external-link" target="_blank">official Deta docs</a>. |
|||
|
|||
## Login with the CLI |
|||
|
|||
Now login to Deta from the CLI with: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ deta login |
|||
|
|||
Please, log in from the web page. Waiting.. |
|||
Logged in successfully. |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
This will open a web browser and authenticate automatically. |
|||
|
|||
## Deploy with Deta |
|||
|
|||
Next, deploy your application with the Deta CLI: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ deta new |
|||
|
|||
Successfully created a new micro |
|||
|
|||
// Notice the "endpoint" 🔍 |
|||
|
|||
{ |
|||
"name": "fastapideta", |
|||
"runtime": "python3.7", |
|||
"endpoint": "https://qltnci.deta.dev", |
|||
"visor": "enabled", |
|||
"http_auth": "enabled" |
|||
} |
|||
|
|||
Adding dependencies... |
|||
|
|||
|
|||
---> 100% |
|||
|
|||
|
|||
Successfully installed fastapi-0.61.1 pydantic-1.7.2 starlette-0.13.6 |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
You will see a JSON message similar to: |
|||
|
|||
```JSON hl_lines="4" |
|||
{ |
|||
"name": "fastapideta", |
|||
"runtime": "python3.7", |
|||
"endpoint": "https://qltnci.deta.dev", |
|||
"visor": "enabled", |
|||
"http_auth": "enabled" |
|||
} |
|||
``` |
|||
|
|||
!!! tip |
|||
Your deployment will have a different `"endpoint"` URL. |
|||
|
|||
## Check it |
|||
|
|||
Now open your browser in your `endpoint` URL. In the example above it was `https://qltnci.deta.dev`, but yours will be different. |
|||
|
|||
You will see the JSON response from your FastAPI app: |
|||
|
|||
```JSON |
|||
{ |
|||
"Hello": "World" |
|||
} |
|||
``` |
|||
|
|||
And now go to the `/docs` for your API, in the example above it would be `https://qltnci.deta.dev/docs`. |
|||
|
|||
It will show your docs like: |
|||
|
|||
<img src="/img/deployment/deta/image01.png"> |
|||
|
|||
## Enable public access |
|||
|
|||
By default, Deta will handle authentication using cookies for your account. |
|||
|
|||
But once you are ready, you can make it public with: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ deta auth disable |
|||
|
|||
Successfully disabled http auth |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
Now you can share that URL with anyone and they will be able to access your API. 🚀 |
|||
|
|||
## HTTPS |
|||
|
|||
Congrats! You deployed your FastAPI app to Deta! 🎉 🍰 |
|||
|
|||
Also notice that Deta correctly handles HTTPS for you, so you don't have to take care of that and can be sure that your clients will have a secure encrypted connection. ✅ 🔒 |
|||
|
|||
## Check the Visor |
|||
|
|||
From your docs UI (they will be in a URL like `https://qltnci.deta.dev/docs`) send a request to your *path operation* `/items/{item_id}`. |
|||
|
|||
For example with ID `5`. |
|||
|
|||
Now go to <a href="https://web.deta.sh/" class="external-link" target="_blank">https://web.deta.sh</a>. |
|||
|
|||
You will see there's a section to the left called <abbr title="it comes from Micro(server)">"Micros"</abbr> with each of your apps. |
|||
|
|||
You will see a tab with "Details", and also a tab "Visor", go to the tab "Visor". |
|||
|
|||
In there you can inspect the recent requests sent to your app. |
|||
|
|||
You can also edit them and re-play them. |
|||
|
|||
<img src="/img/deployment/deta/image02.png"> |
|||
|
|||
## Learn more |
|||
|
|||
At some point you will probably want to store some data for your app in a way that persists through time. For that you can use <a href="https://docs.deta.sh/docs/base/py_tutorial?ref=fastapi" class="external-link" target="_blank">Deta Base</a>, it also has a generous **free tier**. |
|||
|
|||
You can also read more in the <a href="https://docs.deta.sh?ref=fastapi" class="external-link" target="_blank">Deta Docs</a>. |
@ -0,0 +1,179 @@ |
|||
# Deploy with Docker |
|||
|
|||
In this section you'll see instructions and links to guides to know how to: |
|||
|
|||
* Make your **FastAPI** application a Docker image/container with maximum performance. In about **5 min**. |
|||
* (Optionally) understand what you, as a developer, need to know about HTTPS. |
|||
* Set up a Docker Swarm mode cluster with automatic HTTPS, even on a simple $5 USD/month server. In about **20 min**. |
|||
* Generate and deploy a full **FastAPI** application, using your Docker Swarm cluster, with HTTPS, etc. In about **10 min**. |
|||
|
|||
You can use <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a> for deployment. It has several advantages like security, replicability, development simplicity, etc. |
|||
|
|||
If you are using Docker, you can use the official Docker image: |
|||
|
|||
## <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a> |
|||
|
|||
This image has an "auto-tuning" mechanism included, so that you can just add your code and get very high performance automatically. And without making sacrifices. |
|||
|
|||
But you can still change and update all the configurations with environment variables or configuration files. |
|||
|
|||
!!! tip |
|||
To see all the configurations and options, go to the Docker image page: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. |
|||
|
|||
## Create a `Dockerfile` |
|||
|
|||
* Go to your project directory. |
|||
* Create a `Dockerfile` with: |
|||
|
|||
```Dockerfile |
|||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7 |
|||
|
|||
COPY ./app /app |
|||
``` |
|||
|
|||
### Bigger Applications |
|||
|
|||
If you followed the section about creating [Bigger Applications with Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}, your `Dockerfile` might instead look like: |
|||
|
|||
```Dockerfile |
|||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7 |
|||
|
|||
COPY ./app /app/app |
|||
``` |
|||
|
|||
### Raspberry Pi and other architectures |
|||
|
|||
If you are running Docker in a Raspberry Pi (that has an ARM processor) or any other architecture, you can create a `Dockerfile` from scratch, based on a Python base image (that is multi-architecture) and use Uvicorn alone. |
|||
|
|||
In this case, your `Dockerfile` could look like: |
|||
|
|||
```Dockerfile |
|||
FROM python:3.7 |
|||
|
|||
RUN pip install fastapi uvicorn |
|||
|
|||
EXPOSE 80 |
|||
|
|||
COPY ./app /app |
|||
|
|||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] |
|||
``` |
|||
|
|||
## Create the **FastAPI** Code |
|||
|
|||
* Create an `app` directory and enter in it. |
|||
* Create a `main.py` file with: |
|||
|
|||
```Python |
|||
from typing import Optional |
|||
|
|||
from fastapi import FastAPI |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/") |
|||
def read_root(): |
|||
return {"Hello": "World"} |
|||
|
|||
|
|||
@app.get("/items/{item_id}") |
|||
def read_item(item_id: int, q: Optional[str] = None): |
|||
return {"item_id": item_id, "q": q} |
|||
``` |
|||
|
|||
* You should now have a directory structure like: |
|||
|
|||
``` |
|||
. |
|||
├── app |
|||
│ └── main.py |
|||
└── Dockerfile |
|||
``` |
|||
|
|||
## Build the Docker image |
|||
|
|||
* Go to the project directory (in where your `Dockerfile` is, containing your `app` directory). |
|||
* Build your FastAPI image: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ docker build -t myimage . |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
## Start the Docker container |
|||
|
|||
* Run a container based on your image: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ docker run -d --name mycontainer -p 80:80 myimage |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
Now you have an optimized FastAPI server in a Docker container. Auto-tuned for your current server (and number of CPU cores). |
|||
|
|||
## Check it |
|||
|
|||
You should be able to check it in your Docker container's URL, for example: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> or <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (or equivalent, using your Docker host). |
|||
|
|||
You will see something like: |
|||
|
|||
```JSON |
|||
{"item_id": 5, "q": "somequery"} |
|||
``` |
|||
|
|||
## Interactive API docs |
|||
|
|||
Now you can go to <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> or <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (or equivalent, using your Docker host). |
|||
|
|||
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>): |
|||
|
|||
 |
|||
|
|||
## Alternative API docs |
|||
|
|||
And you can also go to <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> or <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (or equivalent, using your Docker host). |
|||
|
|||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>): |
|||
|
|||
 |
|||
|
|||
## Traefik |
|||
|
|||
<a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a> is a high performance reverse proxy / load balancer. It can do the "TLS Termination Proxy" job (apart from other features). |
|||
|
|||
It has integration with Let's Encrypt. So, it can handle all the HTTPS parts, including certificate acquisition and renewal. |
|||
|
|||
It also has integrations with Docker. So, you can declare your domains in each application configurations and have it read those configurations, generate the HTTPS certificates and serve HTTPS to your application automatically, without requiring any change in its configuration. |
|||
|
|||
--- |
|||
|
|||
With this information and tools, continue with the next section to combine everything. |
|||
|
|||
## Docker Swarm mode cluster with Traefik and HTTPS |
|||
|
|||
You can have a Docker Swarm mode cluster set up in minutes (about 20 min) with a main Traefik handling HTTPS (including certificate acquisition and renewal). |
|||
|
|||
By using Docker Swarm mode, you can start with a "cluster" of a single machine (it can even be a $5 USD / month server) and then you can grow as much as you need adding more servers. |
|||
|
|||
To set up a Docker Swarm Mode cluster with Traefik and HTTPS handling, follow this guide: |
|||
|
|||
### <a href="https://medium.com/@tiangolo/docker-swarm-mode-and-traefik-for-a-https-cluster-20328dba6232" class="external-link" target="_blank">Docker Swarm Mode and Traefik for an HTTPS cluster</a> |
|||
|
|||
### Deploy a FastAPI application |
|||
|
|||
The easiest way to set everything up, would be using the [**FastAPI** Project Generators](../project-generation.md){.internal-link target=_blank}. |
|||
|
|||
It is designed to be integrated with this Docker Swarm cluster with Traefik and HTTPS described above. |
|||
|
|||
You can generate a project in about 2 min. |
|||
|
|||
The generated project has instructions to deploy it, doing it takes another 2 min. |
@ -0,0 +1,48 @@ |
|||
# About HTTPS |
|||
|
|||
It is easy to assume that HTTPS is something that is just "enabled" or not. |
|||
|
|||
But it is way more complex than that. |
|||
|
|||
!!! tip |
|||
If you are in a hurry or don't care, continue with the next sections for step by step instructions to set everything up with different techniques. |
|||
|
|||
To learn the basics of HTTPS, from a consumer perspective, check <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>. |
|||
|
|||
Now, from a developer's perspective, here are several things to have in mind while thinking about HTTPS: |
|||
|
|||
* For HTTPS, the server needs to have "certificates" generated by a third party. |
|||
* Those certificates are actually acquired from the third-party, not "generated". |
|||
* Certificates have a lifetime. |
|||
* They expire. |
|||
* And then they need to be renewed, acquired again from the third party. |
|||
* The encryption of the connection happens at the TCP level. |
|||
* That's one layer below HTTP. |
|||
* So, the certificate and encryption handling is done before HTTP. |
|||
* TCP doesn't know about "domains". Only about IP addresses. |
|||
* The information about the specific domain requested goes in the HTTP data. |
|||
* The HTTPS certificates "certify" a certain domain, but the protocol and encryption happen at the TCP level, before knowing which domain is being dealt with. |
|||
* By default, that would mean that you can only have one HTTPS certificate per IP address. |
|||
* No matter how big your server is or how small each application you have on it might be. |
|||
* There is a solution to this, however. |
|||
* There's an extension to the TLS protocol (the one handling the encryption at the TCP level, before HTTP) called <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication">SNI</abbr></a>. |
|||
* This SNI extension allows one single server (with a single IP address) to have several HTTPS certificates and serve multiple HTTPS domains/applications. |
|||
* For this to work, a single component (program) running on the server, listening on the public IP address, must have all the HTTPS certificates in the server. |
|||
* After obtaining a secure connection, the communication protocol is still HTTP. |
|||
* The contents are encrypted, even though they are being sent with the HTTP protocol. |
|||
|
|||
It is a common practice to have one program/HTTP server running on the server (the machine, host, etc.) and managing all the HTTPS parts : sending the decrypted HTTP requests to the actual HTTP application running in the same server (the **FastAPI** application, in this case), take the HTTP response from the application, encrypt it using the appropriate certificate and sending it back to the client using HTTPS. This server is often called a <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">TLS Termination Proxy</a>. |
|||
|
|||
## Let's Encrypt |
|||
|
|||
Before Let's Encrypt, these HTTPS certificates were sold by trusted third-parties. |
|||
|
|||
The process to acquire one of these certificates used to be cumbersome, require quite some paperwork and the certificates were quite expensive. |
|||
|
|||
But then <a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a> was created. |
|||
|
|||
It is a project from the Linux Foundation. It provides HTTPS certificates for free. In an automated way. These certificates use all the standard cryptographic security, and are short lived (about 3 months), so the security is actually better because of their reduced lifespan. |
|||
|
|||
The domains are securely verified and the certificates are generated automatically. This also allows automating the renewal of these certificates. |
|||
|
|||
The idea is to automate the acquisition and renewal of these certificates, so that you can have secure HTTPS, for free, forever. |
@ -0,0 +1,7 @@ |
|||
# Deployment - Intro |
|||
|
|||
Deploying a **FastAPI** application is relatively easy. |
|||
|
|||
There are several ways to do it depending on your specific use case and the tools that you use. |
|||
|
|||
You will see more details to have in mind and some of the techniques to do it in the next sections. |
@ -0,0 +1,69 @@ |
|||
# Deploy manually |
|||
|
|||
You can deploy **FastAPI** manually as well. |
|||
|
|||
You just need to install an ASGI compatible server like: |
|||
|
|||
=== "Uvicorn" |
|||
|
|||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, a lightning-fast ASGI server, built on uvloop and httptools. |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install uvicorn |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
=== "Hypercorn" |
|||
|
|||
* <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, an ASGI server also compatible with HTTP/2. |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install hypercorn |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
...or any other ASGI server. |
|||
|
|||
And run your application the same way you have done in the tutorials, but without the `--reload` option, e.g.: |
|||
|
|||
=== "Uvicorn" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ uvicorn main:app --host 0.0.0.0 --port 80 |
|||
|
|||
<span style="color: green;">INFO</span>: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
=== "Hypercorn" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ hypercorn main:app --bind 0.0.0.0:80 |
|||
|
|||
Running on 0.0.0.0:8080 over http (CTRL + C to quit) |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
You might want to set up some tooling to make sure it is restarted automatically if it stops. |
|||
|
|||
You might also want to install <a href="https://gunicorn.org/" class="external-link" target="_blank">Gunicorn</a> and <a href="https://www.uvicorn.org/#running-with-gunicorn" class="external-link" target="_blank">use it as a manager for Uvicorn</a>, or use Hypercorn with multiple workers. |
|||
|
|||
Making sure to fine-tune the number of workers, etc. |
|||
|
|||
But if you are doing all that, you might just use the Docker image that does it automatically. |
@ -0,0 +1,87 @@ |
|||
# About FastAPI versions |
|||
|
|||
**FastAPI** is already being used in production in many applications and systems. And the test coverage is kept at 100%. But its development is still moving quickly. |
|||
|
|||
New features are added frequently, bugs are fixed regularly, and the code is still continuously improving. |
|||
|
|||
That's why the current versions are still `0.x.x`, this reflects that each version could potentially have breaking changes. This follows the <a href="https://semver.org/" class="external-link" target="_blank">Semantic Versioning</a> conventions. |
|||
|
|||
You can create production applications with **FastAPI** right now (and you have probably been doing it for some time), you just have to make sure that you use a version that works correctly with the rest of your code. |
|||
|
|||
## Pin your `fastapi` version |
|||
|
|||
The first thing you should do is to "pin" the version of **FastAPI** you are using to the specific latest version that you know works correctly for your application. |
|||
|
|||
For example, let's say you are using version `0.45.0` in your app. |
|||
|
|||
If you use a `requirements.txt` file you could specify the version with: |
|||
|
|||
```txt |
|||
fastapi==0.45.0 |
|||
``` |
|||
|
|||
that would mean that you would use exactly the version `0.45.0`. |
|||
|
|||
Or you could also pin it with: |
|||
|
|||
```txt |
|||
fastapi>=0.45.0,<0.46.0 |
|||
``` |
|||
|
|||
that would mean that you would use the versions `0.45.0` or above, but less than `0.46.0`, for example, a version `0.45.2` would still be accepted. |
|||
|
|||
If you use any other tool to manage your installations, like Poetry, Pipenv, or others, they all have a way that you can use to define specific versions for your packages. |
|||
|
|||
## Available versions |
|||
|
|||
You can see the available versions (e.g. to check what is the current latest) in the [Release Notes](../release-notes.md){.internal-link target=_blank}. |
|||
|
|||
## About versions |
|||
|
|||
Following the Semantic Versioning conventions, any version below `1.0.0` could potentially add breaking changes. |
|||
|
|||
FastAPI also follows the convention that any "PATCH" version change is for bug fixes and non-breaking changes. |
|||
|
|||
!!! tip |
|||
The "PATCH" is the last number, for example, in `0.2.3`, the PATCH version is `3`. |
|||
|
|||
So, you should be able to pin to a version like: |
|||
|
|||
```txt |
|||
fastapi>=0.45.0,<0.46.0 |
|||
``` |
|||
|
|||
Breaking changes and new features are added in "MINOR" versions. |
|||
|
|||
!!! tip |
|||
The "MINOR" is the number in the middle, for example, in `0.2.3`, the MINOR version is `2`. |
|||
|
|||
## Upgrading the FastAPI versions |
|||
|
|||
You should add tests for your app. |
|||
|
|||
With **FastAPI** it's very easy (thanks to Starlette), check the docs: [Testing](../tutorial/testing.md){.internal-link target=_blank} |
|||
|
|||
After you have tests, then you can upgrade the **FastAPI** version to a more recent one, and make sure that all your code is working correctly by running your tests. |
|||
|
|||
If everything is working, or after you make the necessary changes, and all your tests are passing, then you can pin your `fastapi` to that new recent version. |
|||
|
|||
## About Starlette |
|||
|
|||
You shouldn't pin the version of `starlette`. |
|||
|
|||
Different versions of **FastAPI** will use a specific newer version of Starlette. |
|||
|
|||
So, you can just let **FastAPI** use the correct Starlette version. |
|||
|
|||
## About Pydantic |
|||
|
|||
Pydantic includes the tests for **FastAPI** with its own tests, so new versions of Pydantic (above `1.0.0`) are always compatible with FastAPI. |
|||
|
|||
You can pin Pydantic to any version above `1.0.0` that works for you and below `2.0.0`. |
|||
|
|||
For example: |
|||
|
|||
```txt |
|||
pydantic>=1.2.0,<2.0.0 |
|||
``` |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 9.9 KiB |
Loading…
Reference in new issue