committed by
GitHub
8 changed files with 269 additions and 102 deletions
@ -1,25 +1,124 @@ |
|||||
# FastAPI Project - Deployment |
# FastAPI Project - Deployment |
||||
|
|
||||
You can deploy the using Docker Compose with a main Traefik proxy outside handling communication to the outside world and HTTPS certificates. |
You can deploy the project using Docker Compose in a remote server. |
||||
|
|
||||
And you can use CI (continuous integration) systems to do it automatically. |
It expects you to have a Traefik proxy handling communication to the outside world and HTTPS certificates. |
||||
|
|
||||
|
And you can use CI (continuous integration) systems to deploy automatically. |
||||
|
|
||||
But you have to configure a couple things first. |
But you have to configure a couple things first. |
||||
|
|
||||
## Traefik network |
## Preparation |
||||
|
|
||||
|
* Have a remote server ready and available. |
||||
|
* Configure the DNS records of your domain to point to the IP of the server you just created. |
||||
|
* Install and configure [Docker](https://docs.docker.com/engine/install/). |
||||
|
* Create a remote directory to store your code, for example: |
||||
|
|
||||
|
```bash |
||||
|
mkdir -p /root/code/fastapi-project/ |
||||
|
``` |
||||
|
|
||||
|
## Public Traefik |
||||
|
|
||||
|
We need a Traefik proxy to handle incoming connections and HTTPS certificates. |
||||
|
|
||||
|
### Traefik Docker Compose |
||||
|
|
||||
|
Copy the Traefik Docker Compose file to your server, to your code directory. You could do it with `rsync`: |
||||
|
|
||||
|
```bash |
||||
|
rsync -a docker-compose.traefik.yml root@your-server.example.com:/root/code/fastapi-project/ |
||||
|
``` |
||||
|
|
||||
|
### Traefik Public Network |
||||
|
|
||||
|
This Traefik will expect a Docker "public network" named `traefik-public` to communicate with your stack(s). |
||||
|
|
||||
|
This way, there will be a single public Traefik proxy that handles the communication (HTTP and HTTPS) with the outside world, and then behind that, you could have one or more stacks. |
||||
|
|
||||
This stack expects the public Traefik network to be named `traefik-public`. |
To create a Docker "public network" named `traefik-public` run: |
||||
|
|
||||
If you need to use a different Traefik public network name, update it in the `docker-compose.yml` files, in the section: |
```bash |
||||
|
docker network create traefik-public |
||||
|
``` |
||||
|
|
||||
|
### Traefik Environment Variables |
||||
|
|
||||
|
The Traefik Docker Compose file expects some environment variables to be set. |
||||
|
|
||||
```YAML |
Create the environment variables for HTTP Basic Auth. |
||||
networks: |
|
||||
traefik-public: |
* Create the username, e.g.: |
||||
external: true |
|
||||
|
```bash |
||||
|
export USERNAME=admin |
||||
|
``` |
||||
|
|
||||
|
* Create an environment variable with the password, e.g.: |
||||
|
|
||||
|
```bash |
||||
|
export PASSWORD=changethis |
||||
|
``` |
||||
|
|
||||
|
* Use openssl to generate the "hashed" version of the password and store it in an environment variable: |
||||
|
|
||||
|
```bash |
||||
|
export HASHED_PASSWORD=$(openssl passwd -apr1 $PASSWORD) |
||||
``` |
``` |
||||
|
|
||||
Change `traefik-public` to the name of the used Traefik network. And then update it in the file `.env`: |
* Create an environment variable with the domain name, e.g.: |
||||
|
|
||||
```bash |
```bash |
||||
TRAEFIK_PUBLIC_NETWORK=traefik-public |
export DOMAIN=fastapi-project.example.com |
||||
``` |
``` |
||||
|
|
||||
|
* Create an environment variable with the email for Let's Encrypt, e.g.: |
||||
|
|
||||
|
```bash |
||||
|
export EMAIL=admin@example.com |
||||
|
``` |
||||
|
|
||||
|
### Start the Traefik Docker Compose |
||||
|
|
||||
|
Now with the environment variables set and the `docker-compose.traefik.yml` in place, you can start the Traefik Docker Compose: |
||||
|
|
||||
|
```bash |
||||
|
docker compose -f docker-compose.traefik.yml up -d |
||||
|
``` |
||||
|
|
||||
|
## Deploy the FastAPI Project |
||||
|
|
||||
|
Now that you have Traefik in place you can deploy your FastAPI project with Docker Compose. |
||||
|
|
||||
|
You could configure the variables in the `.env` file to match your domain, or you could override them before running the `docker compose` command. |
||||
|
|
||||
|
For example: |
||||
|
|
||||
|
```bash |
||||
|
export DOMAIN=fastapi-project.example.com |
||||
|
``` |
||||
|
|
||||
|
And then deploy with Docker Compose: |
||||
|
|
||||
|
```bash |
||||
|
docker compose -f docker-compose.yml up -d |
||||
|
``` |
||||
|
|
||||
|
For production you wouldn't want to have the overrides in `docker-compose.override.yml`, so you would need to explicitly specify the file to use, `docker-compose.yml`. |
||||
|
|
||||
|
## URLs |
||||
|
|
||||
|
Replace `fastapi-project.example.com` with your domain: |
||||
|
|
||||
|
Frontend: https://fastapi-project.example.com |
||||
|
|
||||
|
Backend API docs: https://fastapi-project.example.com/docs |
||||
|
|
||||
|
Backend API base URL: https://fastapi-project.example.com/api/ |
||||
|
|
||||
|
PGAdmin: https://pgadmin.fastapi-project.example.com |
||||
|
|
||||
|
Flower: https://flower.fastapi-project.example.com |
||||
|
|
||||
|
Traefik UI: https://traefik.fastapi-project.example.com |
||||
|
@ -0,0 +1,77 @@ |
|||||
|
services: |
||||
|
traefik: |
||||
|
image: traefik:v2.3 |
||||
|
ports: |
||||
|
# Listen on port 80, default for HTTP, necessary to redirect to HTTPS |
||||
|
- 80:80 |
||||
|
# Listen on port 443, default for HTTPS |
||||
|
- 443:443 |
||||
|
restart: always |
||||
|
labels: |
||||
|
# Enable Traefik for this service, to make it available in the public network |
||||
|
- traefik.enable=true |
||||
|
# Use the traefik-public network (declared below) |
||||
|
- traefik.docker.network=traefik-public |
||||
|
# Define the port inside of the Docker service to use |
||||
|
- traefik.http.services.traefik-dashboard.loadbalancer.server.port=8080 |
||||
|
# Make Traefik use this domain (from an environment variable) in HTTP |
||||
|
- traefik.http.routers.traefik-dashboard-http.entrypoints=http |
||||
|
- traefik.http.routers.traefik-dashboard-http.rule=Host(`traefik.${DOMAIN?Variable not set}`) |
||||
|
# traefik-https the actual router using HTTPS |
||||
|
- traefik.http.routers.traefik-dashboard-https.entrypoints=https |
||||
|
- traefik.http.routers.traefik-dashboard-https.rule=Host(`traefik.${DOMAIN?Variable not set}`) |
||||
|
- traefik.http.routers.traefik-dashboard-https.tls=true |
||||
|
# Use the "le" (Let's Encrypt) resolver created below |
||||
|
- traefik.http.routers.traefik-dashboard-https.tls.certresolver=le |
||||
|
# Use the special Traefik service api@internal with the web UI/Dashboard |
||||
|
- traefik.http.routers.traefik-dashboard-https.service=api@internal |
||||
|
# https-redirect middleware to redirect HTTP to HTTPS |
||||
|
- traefik.http.middlewares.https-redirect.redirectscheme.scheme=https |
||||
|
- traefik.http.middlewares.https-redirect.redirectscheme.permanent=true |
||||
|
# traefik-http set up only to use the middleware to redirect to https |
||||
|
- traefik.http.routers.traefik-dashboard-http.middlewares=https-redirect |
||||
|
# admin-auth middleware with HTTP Basic auth |
||||
|
# Using the environment variables USERNAME and HASHED_PASSWORD |
||||
|
- traefik.http.middlewares.admin-auth.basicauth.users=${USERNAME?Variable not set}:${HASHED_PASSWORD?Variable not set} |
||||
|
# Enable HTTP Basic auth, using the middleware created above |
||||
|
- traefik.http.routers.traefik-dashboard-https.middlewares=admin-auth |
||||
|
volumes: |
||||
|
# Add Docker as a mounted volume, so that Traefik can read the labels of other services |
||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro |
||||
|
# Mount the volume to store the certificates |
||||
|
- traefik-public-certificates:/certificates |
||||
|
command: |
||||
|
# Enable Docker in Traefik, so that it reads labels from Docker services |
||||
|
- --providers.docker |
||||
|
# Do not expose all Docker services, only the ones explicitly exposed |
||||
|
- --providers.docker.exposedbydefault=false |
||||
|
# Create an entrypoint "http" listening on port 80 |
||||
|
- --entrypoints.http.address=:80 |
||||
|
# Create an entrypoint "https" listening on port 443 |
||||
|
- --entrypoints.https.address=:443 |
||||
|
# Create the certificate resolver "le" for Let's Encrypt, uses the environment variable EMAIL |
||||
|
- --certificatesresolvers.le.acme.email=${EMAIL?Variable not set} |
||||
|
# Store the Let's Encrypt certificates in the mounted volume |
||||
|
- --certificatesresolvers.le.acme.storage=/certificates/acme.json |
||||
|
# Use the TLS Challenge for Let's Encrypt |
||||
|
- --certificatesresolvers.le.acme.tlschallenge=true |
||||
|
# Enable the access log, with HTTP requests |
||||
|
- --accesslog |
||||
|
# Enable the Traefik log, for configurations and errors |
||||
|
- --log |
||||
|
# Enable the Dashboard and API |
||||
|
- --api |
||||
|
networks: |
||||
|
# Use the public network created to be shared between Traefik and |
||||
|
# any other service that needs to be publicly available with HTTPS |
||||
|
- traefik-public |
||||
|
|
||||
|
volumes: |
||||
|
# Create a volume to store the certificates, even if the container is recreated |
||||
|
traefik-public-certificates: |
||||
|
|
||||
|
networks: |
||||
|
# Use the previously created public network "traefik-public", shared with other |
||||
|
# services that need to be publicly available via this Traefik |
||||
|
traefik-public: |
||||
|
external: true |
Loading…
Reference in new issue