Django Configure a separate domain name for each App

Environment: Python 3.8.1 + Django 2.2.12

To integrate process specifications, integrated projects including task, doc, sso are deployed.

Approximate directory structure:

CellMiddle -- Project Root Directory
 - task - demand system
│  ├─migrations
│  ├─static
│  └─templates
 - logs - Log directory
 -doc - Document System
│  ├─data
│  ├─migrations
│  ├─static
│  └─templates
 -sso - - Single sign-on, rights control system
│  ├─migrations
│  ├─static
│  └─templates
 - upload - - File resource upload directory
 -static - static resource
 - templates - Common Templates
 - CellMiddle - Project Home Directory
 -config - Public Configuration
 - helper - Public auxiliary class, ex: time, date, string, response, etc.
- loader - Instantiated loading of third-party libraries, ex:Redis, Memcached, etc.
│    │  settings.py
│    │  urls.py
│    │  wsgi.py
│    │  __init__.py
├─manage.py
 - envConf -- Deployment configuration file: requirement.txt, host.conf, supervisor, gunicorn, etc.

Using nginx + gunicorn + supervisor deployment, resolving to server using domain name cell.hao456.com, nginx listens on gunicorn-bound ports and can access them normally:

http://cell.hao456.com/task
http://cell.hao456.com/doc
http://cell.hao456.com/sso

Although the same domain name routing control is accessible, it is also possible.But just like PHP, as long as you have separate entry files, each app uses different subdomains independently, such as:

http://task.hao456.com points to task
http://doc.hao456.com points to doc
http://sso.hao456.com points to sso

Several approaches have been tried:

  1. nginx layer forwarding;
    • Modify proxy pointing to add app, static, etc. to location.
  2. Each app has a separate wsgi.py file, served separately using gunicorn;
    • Add task_wsgi.py, doc_wsgi.py, sso_wsgi.py, and use supervisor to start three gunicorn services.
  3. Use django-hosts;
    • Add MIDDLEWARE middleware to associate host with namespace of urls.The conf configuration of nginx does not need to be changed, only the conf configuration of nginx needs to be changed Listen on all subdomains, proxy to gunicorn port together,
$ cat hosts.conf
server {
    listen 80;
    server_name task.hao456.com doc.hao456.com sso.hao456.com;
    location / {
        proxy_pass http://127.0.0.1:10888;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 120s;
    }
    ... ...
}

django-hosts implementation:

  1. pip installs django-hosts, using version 4.0:
    $ pip install django-hosts==4.0  # root permissions
  1. Modify settings.py:
    • Add django-hosts to app:
    INSTALLED_APPS = [
        ...
        'django_hosts',
        'sso',
        'doc',
        'task',
    ]
- Add Django's hosts configuration:
    ROOT_HOSTCONF = 'CellMiddle.hosts'  # host configuration
    DEFAULT_HOST = 'sso'  # Default domain name
- Add django_hosts to the middleware MIDDLEWARE:
    MIDDLEWARE = [
    'django_hosts.middleware.HostsRequestMiddleware',  # First plus
    ...
    'django_hosts.middleware.HostsRequestMiddleware',  # End to add
]
  1. In the project home directory, add hosts.py siblings (note the ROOT_HOSTCONF configured in settings):
...
└─CellMiddle
    │  hosts.py  --- Add Files
    │  settings.py
    │  urls.py
    │  wsgi.py
    │  __init__.py

The content is:

# coding=utf8
    """
    django-hosts
    """
    from django.conf import settings
    from django_hosts import patterns, host

    host_patterns = patterns(
        '',
        host('sso', settings.ROOT_URLCONF, name='sso'),
        host('doc', 'doc.urls', name='doc'),
        host('task', 'task.urls', name='task'),
    )
  1. Route configuration urls.py, add the corresponding appname (app name), namespace (domain name):
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', include(('sso.urls', 'sso'), namespace='sso')),  # Default sso
        path('doc', include(('doc.urls', 'doc'), namespace='doc')),  # File
        path('task', include(('task.urls', 'task'), namespace='task')),  # demand
    ]
  1. reload overload service:
  • DNS confirmation subdomain name resolution;
  • Check the configuration validity of nginx, overload nginx;
  • Update the Web service dynamically or restart the Web service in supervisorctl;
$ kill -HUP PID  # root permissions
$ supervisorctl restart program_name service name  # root permissions
  1. Check whether subdomain name access, app routing, static resource access, etc. are normal;

Tags: Programming Django Nginx supervisor pip

Posted on Fri, 08 May 2020 10:54:19 -0700 by leegreaves