Django 没有捕获来自 Traefik 的请求

Django does not catch the requests from Traefik

我最近配置了 traefik 来管理我的子域及其证书 (LetsEncrypt)。所以目前一共有三个服务:traefik本身,nginx(用于处理静态文件,还没有完全配置)和django。所有这些服务都运行良好且没有错误。但是我的 traefik 和我的 django 应用程序之间的通信运气不好。下面我给大家展示一下我的项目文件夹结构和配置文件,如果有人能帮忙就太好了。

.
├── proxy
│   ├── acme.json
│   ├── docker-compose.yml
│   └── traefik.toml
└── services
    ├── django
    │   ├── docker-compose.yml
    │   ├── Dockerfile
    │   ├── example
    │   │   ├── asgi.py
    │   │   ├── __init__.py
    │   │   ├── settings
    │   │   │   ├── base.py
    │   │   │   ├── dev.py
    │   │   │   ├── __init__.py
    │   │   │   └── prod.py
    │   │   ├── urls.py
    │   │   └── wsgi.py
    │   ├── manage.py
    │   ├── media
    │   ├── Pipfile
    │   ├── Pipfile.lock
    │   ├── scripts
    │   │   ├── entrypoint.sh
    │   │   └── entrypoint.sh_backup
    │   └── staticfiles
    └── nginx
        ├── default.conf
        └── docker-compose.yml

# cat proxy/traefik.toml

[accessLog]

[log]
  level = "INFO"

[api]
  dashboard = true
  insecure = false

[providers]
  [providers.docker]
    exposedByDefault = false
    watch = true
    network = "web"


[entryPoints]
  [entryPoints.web]
    address = ":80"

  [entryPoints.web-secure]
    address = ":443"


[certificatesResolvers]
  [certificatesResolvers.letsEncrypt.acme]
    email = "example@gmail.com"
    storage = "acme.json"
    [certificatesResolvers.letsEncrypt.acme.httpChallenge]
      entryPoint = "web"
    [certificatesResolvers.letsEncrypt.acme.tlsChallenge]

# cat proxy/docker-compose.yml

version: '3.7'

services:
    traefik:
        image: traefik:latest
        container_name: traefik
        restart: always
        labels:
           - "traefik.enable=true"
           - "traefik.http.routers.${SERVICE}.rule=Host(`${DOMAIN_NAME}`)"
           - "traefik.http.routers.${SERVICE}.service=api@internal"
           - "traefik.http.routers.${SERVICE}.tls.certresolver=letsEncrypt"
           - "traefik.http.routers.${SERVICE}.entrypoints=web-secure"
           - "traefik.http.routers.${SERVICE}.middlewares=${SERVICE}_auth"
           - "traefik.http.middlewares.${SERVICE}_auth.basicauth.users=example:example"
           - "traefik.http.middlewares.${SERVICE}_https.redirectscheme.scheme=https"
           - "traefik.http.routers.${SERVICE}_redirect.rule=Host(`${DOMAIN_NAME}`)"
           - "traefik.http.routers.${SERVICE}_redirect.entrypoints=web"
           - "traefik.http.routers.${SERVICE}_redirect.middlewares=${SERVICE}_https"
           - "com.centurylinklabs.watchtower.enable=true"
        ports:
            - 80:80
            - 443:443
        volumes:
           - /var/run/docker.sock:/var/run/docker.sock
           - ./traefik.toml:/traefik.toml
           - ./acme.json:/acme.json
        networks:
            - web

networks:
    web:
       external: true

# cat services/django/docker-compose.yml

version: '3.7'

services:
    django:
        container_name: dj
        build:
            context: ./
        restart: unless-stopped
        labels:
           - "traefik.enable=true"
           - "traefik.http.routers.${SERVICE}.rule=Host(`${DOMAIN_NAME}`)"
           - "traefik.http.routers.${SERVICE}.tls.certresolver=letsEncrypt"
           - "traefik.http.routers.${SERVICE}.entrypoints=web-secure"
           - "traefik.http.services.${SERVICE}.loadbalancer.server.port=5000"
        volumes:
           - staticfiles:/app/staticfiles
           - mediafiles:/app/media
        env_file: .env
        command: gunicorn example.wsgi:application --bind 0.0.0.0:5000 -k uvicorn.workers.UvicornWorker
        expose:
            - 5000
        networks:
            - web

volumes:
    staticfiles:
    mediafiles:

networks:
    web:
        external: true

正如我之前所说,所有这些服务都是独立运行的,没有错误。我的问题其实是我哪里做错了,为什么Django收不到Traefik的请求?

这里还有 Traefik 和 Django 在页面重新加载时的日志:

# TRAEFIK LOGS
31.24.11.55 - - [29/Aug/2020:03:11:16 +0000] "GET / HTTP/1.1" 404 19 "-" "-" 375 "-" "-" 0ms
31.24.11.55 - - [29/Aug/2020:03:11:16 +0000] "GET / HTTP/1.1" 404 19 "-" "-" 376 "-" "-" 0ms
31.24.11.55 - - [29/Aug/2020:03:11:17 +0000] "GET / HTTP/1.1" 404 19 "-" "-" 377 "-" "-" 0ms
31.24.11.55 - - [29/Aug/2020:03:11:17 +0000] "GET / HTTP/1.1" 404 19 "-" "-" 378 "-" "-" 0ms


# DJANGO LOGS
165 static files copied to '/app/staticfiles'.
[2020-08-29 02:36:29 +0000] [1] [INFO] Starting gunicorn 20.0.4
[2020-08-29 02:36:29 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
[2020-08-29 02:36:29 +0000] [1] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2020-08-29 02:36:29 +0000] [11] [INFO] Booting worker with pid: 11
Debugging status is:  False
[2020-08-29 02:36:30 +0000] [11] [INFO] Started server process [11]
[2020-08-29 02:36:30 +0000] [11] [INFO] Waiting for application startup.
[2020-08-29 02:36:30 +0000] [11] [INFO] ASGI 'lifespan' protocol appears unsupported.
[2020-08-29 02:36:30 +0000] [11] [INFO] Application startup complete.

天哪,我浪费了这么多时间。问题很简单 ALLOWED_HOSTS (Facepalm).

我打开 DEBUG=True,然后我才能够看到错误是由 ALLOWED_HOSTS 引起的。只需将主机添加到此列表即可解决我的问题!

所以伙计们总是在初始部署时打开 DEGUB=True 以发现任何问题。