[Answered ]-Django serve multiple domains with a single instance

1👍

Please figure out if you can try this.

in a middleware module, check what is the hostname. set the DB based on the hostname.

import socket

try:
    hostname = socket.gethostname()
except:
    hostname = 'default'

if hostname == 'site1.com':

  DATABASES = {
      'default': {
          'ENGINE': 'django.db.backends.mysql',
          'NAME': 'site1DB',
          'USER': 'root',
          'PASSWORD': '*****',
          'HOST': 'localhost',   
          'PORT': '3306',
      }
  }


elif hostname == 'site2.com':

  DATABASES = {
      'default': {
          'ENGINE': 'django.db.backends.mysql',
          'NAME': 'site2DB',
          'USER': 'root',
          'PASSWORD': '*****',
          'HOST': 'localhost',   
          'PORT': '3306',
      }
  }

Also please if Django routers (https://docs.djangoproject.com/ja/1.9/topics/db/multi-db/) is helpful.

1👍

You have a few options, which really depends on what you are trying to achieve.

There is this Django app https://github.com/bernardopires/django-tenant-schemas where you can setup multiple databases schemas and serve the requests based on the subdomain. I never tried it though.


I actually had a similar problem once. I needed 7 independent instances of my application, for an usability experiment and I didn’t want to add any extra dependency, because it was temporary.

I cloned my repository in the Ubuntu server, and there I created 7 different databases (db_1, db_2, …, db_7) and created 7 settings file:

settings_1.py

from django_app.settings import *

ENVIRONMENT_NAME = 'Test Environment 1'

DATABASES = {
    'default': dj_database_url.config(
        default = 'postgres://u_db:123@localhost:5432/db_1' 
    )
}

MEDIA_ROOT = PROJECT_DIR.parent.parent.child('media').child('_1')

settings_2.py

from django_app.settings import *

ENVIRONMENT_NAME = 'Test Environment 2'

DATABASES = {
    'default': dj_database_url.config(
        default = 'postgres://u_db:123@localhost:5432/db_2' 
    )
}

MEDIA_ROOT = PROJECT_DIR.parent.parent.child('media').child('_2')

And so on… Basically I was importing my project settings and overriding the parameters I needed, i.e., the database

Then after that I created a gunicorn_start script for each of my environments:

gunicorn_start_1

#!/bin/bash

NAME="django_app_1"
DJANGODIR=/opt/django_app/django_app
SOCKFILE=/opt/django_app/run/gunicorn_1.sock
USER=app_user
GROUP=django_apps
NUM_WORKERS=3
DJANGO_SETTINGS_MODULE=django_app.settings_1
DJANGO_WSGI_MODULE=django_app.wsgi

cd $DJANGODIR
source ../bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR

exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --user=$USER --group=$GROUP \
  --bind=unix:$SOCKFILE \
  --log-level=error \
  --log-file=-

gunicorn_start_2

#!/bin/bash

NAME="django_app_2"
DJANGODIR=/opt/django_app/django_app
SOCKFILE=/opt/django_app/run/gunicorn_2.sock
USER=app_user
GROUP=django_apps
NUM_WORKERS=3
DJANGO_SETTINGS_MODULE=django_app.settings_2
DJANGO_WSGI_MODULE=django_app.wsgi

cd $DJANGODIR
source ../bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR

exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --user=$USER --group=$GROUP \
  --bind=unix:$SOCKFILE \
  --log-level=error \
  --log-file=-

And did the same thing for the rest.

Each of the instances had its own nginx config file:

app_1 (nginx config)

upstream app_server_1 {
  server unix:/opt/django_app/run/gunicorn_1.sock fail_timeout=0;
}

server {
    listen   80;
    server_name env1.mydomain.com;
    client_max_body_size 4G;

    access_log /opt/django_app/logs/nginx-access_1.log;
    error_log /opt/django_app/logs/nginx-error_1.log;

    location /static/ {
        alias   /opt/django_app/static/;
    }

    location /media/ {
        alias   /opt/django_app/media/_1/;
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        if (!-f $request_filename) {
            proxy_pass http://app_server_1;
            break;
        }
    }

}

app_2 (nginx config)

upstream app_server_2 {
  server unix:/opt/django_app/run/gunicorn_2.sock fail_timeout=0;
}

server {
    listen   80;
    server_name env2.mydomain.com;
    client_max_body_size 4G;

    access_log /opt/django_app/logs/nginx-access_2.log;
    error_log /opt/django_app/logs/nginx-error_2.log;

    location /static/ {
        alias   /opt/django_app/static/;
    }

    location /media/ {
        alias   /opt/django_app/media/_2/;
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        if (!-f $request_filename) {
            proxy_pass http://app_server_2;
            break;
        }
    }

}

After that I configured a supervisor for each of the instances and configured the DNS of my domain.

So basically I had a shared Django source code and static files, and independent media folder, log files and databases.


Probably it is not the best approach, but I managed to achieve what I needed at the time

Leave a comment