fastapi / full-stack-fastapi-template

Full stack, modern web application template. Using FastAPI, React, SQLModel, PostgreSQL, Docker, GitHub Actions, automatic HTTPS and more.
MIT License
26.28k stars 4.6k forks source link

Traefik v2 #133

Closed ssspeq closed 4 years ago

ssspeq commented 4 years ago

I am trying to adapt this to use traefik v2 but I cant get it to work. Has anyone tried this?

Also, how would I use this if I already have a docker swarm with traefik v2 that I want to deploy to?

bgottsch commented 4 years ago

This weekend I had the same issue and came to a solution. Still working on HTTPS details, env varibles and a few things. It should be a good starting point.

version: '3.5'

volumes:
  volume_traefik:
  volume_api:
  volume_db:
  volume_pgadmin:
  volume_rabbitmq:
  volume_frontend:

networks:
  web:
    name: web
  backend:
    name: backend

services:

  traefik:
    image: traefik:v2.2
    container_name: traefik
    hostname: traefik
    restart: unless-stopped
    command: 

      - --api.insecure=false # <== Enabling insecure api, NOT RECOMMENDED FOR PRODUCTION
      - --api.dashboard=true # <== Enabling the dashboard to view services, middlewares, routers, etc...
      - --api.debug=true # <== Enabling additional endpoints for debugging and profiling

      - --log.level=DEBUG

      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=web

      - --entrypoints.web.address=:80
      - --entrypoints.web-secured.address=:443

      - --certificatesresolvers.tls-challenge.acme.tlschallenge=true
      - --certificatesresolvers.tls-challenge.acme.email=fake@email.com
      - --certificatesresolvers.tls-challenge.acme.storage=/letsencrypt/acme.json
    depends_on:
      - api
      - db
      - pgadmin
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - volume_traefik:/letsencrypt
    networks:
      - web
    ports:
      - 80:80
      - 443:443
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"

      - "traefik.http.services.traefik.loadbalancer.server.port=8080"

      # redirect all HTTP requests to HTTPS
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      #- "traefik.http.routers.http-catchall.middlewares=https-redirect@docker"

      - "traefik.http.routers.traefik.rule=Host(`traefik.localhost`)"
      - "traefik.http.routers.traefik.entrypoints=web" #-secured"
      #- "traefik.http.routers.traefik.tls.certresolver=tls-challenge"
      - "traefik.http.routers.traefik.middlewares=auth"
      - "traefik.http.routers.traefik.service=api@internal"

      - "traefik.http.middlewares.auth.digestauth.realm=traefik"
      - "traefik.http.middlewares.auth.digestauth.users=admin:traefik:817374111f31cc282162486425ee5e9e"

      #- "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"

  api:
    image: api:latest
    container_name: api
    hostname: api
    restart: unless-stopped
    build:
      context: ./backend
      dockerfile: api.dockerfile
    depends_on:
      - db
    env_file:
      - .env
    volumes:
      - volume_api:/api
      - ./backend/api/alembic:/api/alembic:rw
      - ./backend/api/app:/api/app:rw
      - ./backend/api/scripts:/api/scripts:rw
      - ./backend/api/alembic.ini:/api/alembic.ini:rw
      - ./backend/api/gunicorn_conf.py:/api/gunicorn_conf.py:rw
    networks:
      - web
      - backend
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"

      - "traefik.http.services.api.loadbalancer.server.port=8001"

      - "traefik.http.routers.api.rule=Host(`localhost`) && PathPrefix(`/api`,`/docs`,`/redoc`)"
      - "traefik.http.routers.api.entrypoints=web" #-secured"
      #- "traefik.http.routers.api.tls.certresolver=tls-challenge"
      #- "traefik.http.routers.api.tls.domains[0].main=localhost."
      #- "traefik.http.routers.api.tls.domains[0].sans=*.localhost."

  db:
    image: postgres:11.5-alpine
    container_name: db
    hostname: db
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - volume_db:/var/lib/postgresql/data:rw
    networks:
      - backend

  pgadmin:
    image: dpage/pgadmin4:4
    container_name: pgadmin
    hostname: pgadmin
    restart: unless-stopped
    depends_on:
      - db
    env_file:
      - .env
    volumes:
      - volume_pgadmin:/var/lib/pgadmin:rw
    networks:
      - web
      - backend
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"

      - "traefik.http.services.pgadmin.loadbalancer.server.port=5050"

      - "traefik.http.routers.pgadmin.rule=Host(`pgadmin.localhost`)"
      - "traefik.http.routers.pgadmin.entrypoints=web" #-secured"
      #- "traefik.http.routers.pgadmin.tls.certresolver=tls-challenge"
      #- "traefik.http.routers.pgadmin.tls.domains[0].main=pgadmin.localhost."
      #- "traefik.http.routers.pgadmin.tls.domains[0].sans=*.pgadmin.localhost."

  # celeryworker:
  #   image: celeryworker:latest
  #   container_name: celeryworker
  #   hostname: celeryworker
  #   restart: unless-stopped
  #   build:
  #     context: ./backend
  #     dockerfile: celeryworker.dockerfile
  #   depends_on:
  #     - api
  #     - db
  #     - rabbitmq
  #   env_file:
  #     - .env
  #   volumes:
  #     - ./backend/api/app:/api/app:rw
  #   networks:
  #     - backend

  rabbitmq:
    image: rabbitmq:3
    container_name: rabbitmq
    hostname: rabbitmq
    restart: unless-stopped
    networks:
      - backend
    volumes:
      - volume_rabbitmq:/var/lib/rabbitmq

  # frontend:
  #   image: frontend:latest
  #   container_name: frontend
  #   hostname: frontend
  #   restart: unless-stopped
  #   build:
  #     context: ./frontend
  #     dockerfile: app.dockerfile
  #   networks:
  #     - web
  #     - backend
  #   volumes:
  #     - volume_frontend:/serve
  #   labels:
  #     - "traefik.enable=true"
  #     - "traefik.docker.network=web"

  #     - "traefik.http.services.frontend.loadbalancer.server.port=80"

  #     - "traefik.http.routers.frontend.rule=Host(`localhost`)"
  #     - "traefik.http.routers.frontend.entrypoints=web" #-secured"
  #     #- "traefik.http.routers.frontend.tls.certresolver=tls-challenge"
  #     #- "traefik.http.routers.frontend.tls.domains[0].main=localhost."
  #     #- "traefik.http.routers.frontend.tls.domains[0].sans=*.localhost."

It creates a proxy with Traefik v2 with the following routes:

Also, I use networks to isolate containers. web for the traefik stuff and backend for the internal, non exposed stuff. Note that the api itself is exposed to web and to the backend networks. This is to allow access to it from outside. Also, if made a router in fastapi to set a prefix to every request in the form of /api/v1/...

Let me know if you have any doubts.

lucawen commented 4 years ago

this will be implemented ?

tiangolo commented 4 years ago

Yep. I want to update this project to use Traefik 2, but I have to first update dockerswarm.rocks to use Traefik 2 by default, then update here and the sibling project generators, and do it all in one batch to make sure nothing is broken in the middle of the process, so it will take a bit.

vishalkhondre commented 4 years ago

@tiangolo - could you please provide any help / solution? @bgottsch - Thank you so much! Your example was great help. However its only working for one backedn API, I've one morer separate backedn API. Any idea how I can achieve that? OR what I'm missing in below code - `version: '3.5'

networks: web: name: web backend: name: backend

services:

traefik: image: traefik:v2.2 container_name: traefik hostname: traefik restart: unless-stopped command:

tiangolo commented 4 years ago

Hey everyone! I just finished migrating DockerSwarm.rocks and this project generator to Traefik v2, you can check the new code :tada: :rocket:

github-actions[bot] commented 4 years ago

Assuming the original issue was solved, it will be automatically closed now. But feel free to add more comments or create new issues.