Deploy Django REST + Flutter

I am trying to deploy Flutter web app that consume Django REST API in the backend. And my system also has Celery in background.

production.yml

version: '3'

volumes:
  production_postgres_data: {}
  production_postgres_data_backups: {}
  production_traefik: {}

services:
  flutter:
    build:
      context: .
      dockerfile: ./compose/local/flutter/Dockerfile
    image: send_and_expire_flutter
    container_name: send_and_expire_flutter
    depends_on:
      - django
    ports:
      - "8080:8080"

  django: &django
    build:
      context: .
      dockerfile: ./compose/production/django/Dockerfile
    image: send_and_expire_production_django
    depends_on:
      - postgres
      - redis
    env_file:
      - ./.envs/.production/.django
      - ./.envs/.production/.postgres
    command: /start

  postgres:
    build:
      context: .
      dockerfile: ./compose/production/postgres/Dockerfile
    image: send_and_expire_production_postgres
    volumes:
      - production_postgres_data:/var/lib/postgresql/data:Z
      - production_postgres_data_backups:/backups:z
    env_file:
      - ./.envs/.production/.postgres

  traefik:
    build:
      context: .
      dockerfile: ./compose/production/traefik/Dockerfile
    image: send_and_expire_production_traefik
    depends_on:
      - django
    volumes:
      - production_traefik:/etc/traefik/acme:z
    ports:
      - "0.0.0.0:80:80"
      - "0.0.0.0:443:443"
      - "0.0.0.0:5555:5555"

  redis:
    image: redis:6

  celeryworker:
    <<: *django
    image: send_and_expire_production_celeryworker
    command: /start-celeryworker

  celerybeat:
    <<: *django
    image: send_and_expire_production_celerybeat
    command: /start-celerybeat

  flower:
    <<: *django
    image: send_and_expire_production_flower
    command: /start-flower

  awscli:
    build:
      context: .
      dockerfile: ./compose/production/aws/Dockerfile
    env_file:
      - ./.envs/.production/.django
    volumes:
      - production_postgres_data_backups:/backups:z

urls.py

urlpatterns += [
    # API base url
    path("api/", include("config.api_router")),
    # DRF auth token
    path("api/auth-token/", obtain_auth_token),
    path("api/schema/", SpectacularAPIView.as_view(), name="api-schema"),
    path(
        "api/docs/",
        SpectacularSwaggerView.as_view(url_name="api-schema"),
        name="api-docs",
    ),
]

Because I need to solve CORS problem then I have to use reverse-proxy feature. I add my Flutter route to it. Here is my traefik.yml

log:
  level: INFO

entryPoints:
  web:
    # http
    address: ":80"
    http:
      # https://docs.traefik.io/routing/entrypoints/#entrypoint
      redirections:
        entryPoint:
          to: web-secure

  web-secure:
    # https
    address: ":443"

  flower:
    address: ":5555"

certificatesResolvers:
  letsencrypt:
    # https://docs.traefik.io/master/https/acme/#lets-encrypt
    acme:
      email: "sarit@elcolie.com"
      storage: /etc/traefik/acme/acme.json
      # https://docs.traefik.io/master/https/acme/#httpchallenge
      httpChallenge:
        entryPoint: web

http:
  routers:
    flutter-secure-router:
      rule: "Path(`/`)"
      entryPoints:
        - web-secure
      service: flutter
      tls:
        certResolver: letsencrypt

    web-secure-router:
      rule: "Path(`/api/*`) || Path(`/admin/*`)"
      entryPoints:
        - web-secure
      middlewares:
        - csrf
      service: django
      tls:
        # https://docs.traefik.io/master/routing/routers/#certresolver
        certResolver: letsencrypt

    flower-secure-router:
      rule: "Host(`flower.send-n-expire.link`)"
      entryPoints:
        - flower
      service: flower
      tls:
        # https://docs.traefik.io/master/routing/routers/#certresolver
        certResolver: letsencrypt

  middlewares:
    csrf:
      # https://docs.traefik.io/master/middlewares/headers/#hostsproxyheaders
      # https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
      headers:
        hostsProxyHeaders: ["X-CSRFToken"]

  services:
    flutter:
      loadBalancer:
        servers:
          - url: http://flutter:8080

    django:
      loadBalancer:
        servers:
          - url: http://django:5000

    flower:
      loadBalancer:
        servers:
          - url: http://flower:5555

providers:
  # https://docs.traefik.io/master/providers/file/
  file:
    filename: /etc/traefik/traefik.yml
    watch: true

treafik/Dockefile

FROM traefik:v2.2.11
RUN mkdir -p /etc/traefik/acme \
  && touch /etc/traefik/acme/acme.json \
  && chmod 600 /etc/traefik/acme/acme.json
COPY ./compose/production/traefik/traefik.yml /etc/traefik
traefik_1       | time="2022-01-24T13:44:35Z" level=error msg="Unable to obtain ACME certificate for domains \"send-n-expire.link\": unable to generate a certificate for the domains [send-n-expire.link]: error: one or more domains had a problem:\n[send-n-expire.link] acme: error: 400 :: urn:ietf:params:acme:error:dns :: no valid A records found for send-n-expire.link; no valid AAAA records found for send-n-expire.link, url: \n" routerName=flower-secure-router@file rule="Host(`send-n-expire.link`)" providerName=letsencrypt.acme

DNS supposed to propagate successfully already it has been a day.

Problems:
How to to correctly enable https and route my frontend and backend using Path?
Here is an example

  1. http://flower.send-n-expire.link:5555/ shows 404 and Not secure
  2. https://www.send-n-expire.link/ shows 404 and Not secure
  3. http://www.send-n-expire.link:8080 To prove that container is up and running

To solve my issues

  1. Use another domain name. I use .com
  2. rule is wrong the correct one is
  routers:
    flutter-secure-router:
      rule: "PathPrefix(`/`) && Host(`www.updatafile.com`)"
      entryPoints:
        - web-secure
      service: flutter
      tls:
        certResolver: letsencrypt

    web-secure-router:
      rule: "PathPrefix(`/api/`) || PathPrefix(`/admin/`) && Host(`www.updatafile.com`)"
      entryPoints:
        - web-secure
      middlewares:
        - csrf
      service: django
      tls:
        # https://docs.traefik.io/master/routing/routers/#certresolver
        certResolver: letsencrypt

    flower-secure-router:
      rule: "Host(`flower.updatafile.com`)"
      entryPoints:
        - flower
      service: flower
      tls:
        # https://docs.traefik.io/master/routing/routers/#certresolver
        certResolver: letsencrypt

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.