awesome-compose/caddy-fastapi/README.md
Grant Birkinbine 2dfb65746b
add caddy-fastapi
Signed-off-by: Grant Birkinbine <grantbirki@github.com>
2022-03-17 19:27:06 -07:00

4.3 KiB

Compose sample application

Caddy/FastAPI application

Deploy Caddy + FastAPI with docker-compose

Project structure:

├── docker-compose.yaml
├── Dockerfile
├── requirements.txt
├── src
    ├── caddy
        ├── Caddyfile
        ├── Dockerfile
        ├── start.sh
    ├── caddy
        ├── Dockerfile
        ├── main.py
        ├── requirements.txt

docker-compose.yaml

services:
  fastapi:
    container_name: fastapi
    restart: unless-stopped
    build:
      context: ./src/fastapi
      dockerfile: ./Dockerfile
    ports:
      - 8000:8000
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 5m
      timeout: 5s
      retries: 3
      start_period: 15s

  caddy:
    container_name: caddy
    restart: unless-stopped
    build:
      context: ./src/caddy
      dockerfile: ./Dockerfile
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./data/caddy_data:/data
      - ./data/caddy_config:/config
    depends_on:
      - fastapi
    environment:
      PROXY_BACKEND: fastapi
      PROXY_PORT: 8000
      DOMAIN: ${DOMAIN}

volumes:
  caddy_data:
  caddy_config:

Deploy with docker-compose

docker-compose up --build

Note: You will see WARNING: The DOMAIN variable is not set. Defaulting to a blank string. and that is expected - See the extra info section below for more details

Expected result

Listing containers must show one container running and the port mapping as below:

$ docker ps
CONTAINER ID   IMAGE          COMMAND       CREATED              STATUS              PORTS                                               NAMES
52d5fbe3dc5d   caddy-fastapi_caddy     "sh /app/start.sh"       12 seconds ago   Up 1 second                      0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 2019/tcp   caddy
09677bb1297e   caddy-fastapi_fastapi   "python -m uvicorn m…"   13 seconds ago   Up 1 second (health: starting)   0.0.0.0:8000->8000/tcp

After the application starts, navigate to localhost in your web browser and you should see the following json response:

{"Hello":"World"}

Stop and remove the containers

$ docker-compose down
WARNING: The DOMAIN variable is not set. Defaulting to a blank string.
Stopping caddy   ... done
Stopping fastapi ... done
Removing caddy   ... done
Removing fastapi ... done
Removing network caddy-fastapi_default

Additional Information 📚

This section contains additional information about the docker-compose sample application

TLS Certificate 🔐

Caddy automatically provisions TLS certificates for you. In order to make use of this awesome feature, do the following:

  1. Ensure your server has ports 80 and 443 open

  2. Have a DNS record pointed to your server for the domain you wish to obtain a certificate for (e.g. app.example.org -> <IP address>)

  3. Export the env var for the domain you wish to use:

    export DOMAIN=app.example.org
    
  4. Start the docker-compose stack:

    docker-compose up --build
    
  5. Navigate to your domain and enjoy your easy TLS setup with Caddy! -> https://app.example.org

Extra Extra Info 📚

Here is some extra info about the setup

Volumes 🛢️

The docker-compose file creates two volumes:

  • ./data/caddy_data:/data
  • ./data/caddy_config:/config

The config volume is used to mount Caddy configuration

The data volume is used to store certificate information. This is really important so that you are not re-requesting TLS certs each time you start your container. Doing so can cause you to hit Let's Encrypt rate limits that will prevent you from provisioning certificates.

Environment Variables 📝

If you run the stack without the DOMAIN variable set in your environment, the stack will default to using localhost. This is ideal for testing out the stack locally.

If you set the DOMAIN variable, Caddy will attempt to provision a certificate for that domain. In order to do so, you will need DNS records pointed to that domain and you will need need traffic to access your server via port 80 and 443.