Django + Gunicorn + Nginx Setup

Prior to gunicorn and nginx, i’ve tried to user apache + mod_wsgi and failed. Still don’t know why it fail. After 3 days trying, I give up. I have to look for another method, I try using gunicorn dan nginx, and It took me only 2 days for gunicord + nginx setup to works. 🙂

Here is condition on my Django + Gunicorn + Nginx setup:

  • I use CentOS 7 on my server
  • I create new user for running django (in my case /home/myuser)
  • I install python 3.7.3, django, pandas, django_extensions, virtual environment, gunicorn dan nginx
  • My django project folder is /home/myuser/myproject
  • I put all my django app (created using ‘python manage.py startapp myapp apps/myapp’) in /home/myuser/myproject/apps

Here is some of reference I use:

Here is my setup:

/home/myuser/myproject/wsgi.py

import os
import sys

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
sys.path.append('/home/myuser/myproject/apps')

application = get_wsgi_application()

/etc/nginx/nginx.conf

user  nginx; 
worker_processes  1; 

error_log  /var/log/nginx/error.log warn; 
pid        /var/run/nginx.pid; 


events { 
   worker_connections  1024; 
} 


http { 
   include       /etc/nginx/mime.types; 
   default_type  application/octet-stream; 

   log_format  main  '$remote_addr - $remote_user [$time_local] "$request" ' 
                     '$status $body_bytes_sent "$http_referer" ' 
                     '"$http_user_agent" "$http_x_forwarded_for"'; 

   access_log  /var/log/nginx/access.log  main; 

   sendfile        on; 
   #tcp_nopush     on; 

   keepalive_timeout  65; 

   #gzip  on; 

   include /etc/nginx/conf.d/*.conf; 
}

/etc/systemd/system/gunicorn.service

setup for gunicorn to be run as service.

[Unit] 
Description=gunicorn service 
After=network.target 

[Service] 
User=myuser 
Group=myuser 
WorkingDirectory=/home/myuser/myproject/ 
ExecStart=/home/myuser/app1/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/myuser/myproject/myproject.sock myproject.wsgi:application --log-level debug 

[Install] 
WantedBy=multi-user.target

don’t forget to enable service using:

systemctl enable gunicorn

/home/myuser/myproject/myproject/setting.py

import os 

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 

SECRET_KEY = '6sp(_!o*NOT_MY_REAL_KEY_OF_COURSE*uu5o(9q1+ir=:-)r' # change: my key

DEBUG = True # to be changed on production

ALLOWED_HOSTS = ['192.168.0.2','myuser.mydomain.com'] #change: my domain


# Application definition 

INSTALLED_APPS = [ 
   'django.contrib.admin', 
   'django.contrib.auth', 
   'django.contrib.contenttypes', 
   'django.contrib.sessions', 
   'django.contrib.messages', 
   'django.contrib.staticfiles', 
   'django.contrib.humanize', 
   'django_extensions', 
   'myproject', 
   'myproject.templatetags', # delete:my custom tags
   'login', # delete:my app
   'weeklyreport', # delete:my app
]
MIDDLEWARE = [ 
   'django.middleware.security.SecurityMiddleware', 
   'django.contrib.sessions.middleware.SessionMiddleware', 
   'django.middleware.common.CommonMiddleware', 
   'django.middleware.csrf.CsrfViewMiddleware', 
   'django.contrib.auth.middleware.AuthenticationMiddleware', 
   'django.contrib.messages.middleware.MessageMiddleware', 
   'django.middleware.clickjacking.XFrameOptionsMiddleware', 
] 

ROOT_URLCONF = 'myproject.urls' 

TEMPLATES = [ 
   { 
       'BACKEND': 'django.template.backends.django.DjangoTemplates', 
       'DIRS': ['templates'], 
       'APP_DIRS': True, 
       'OPTIONS': { 
           'context_processors': [ 
               'django.template.context_processors.debug', 
               'django.template.context_processors.request', 
               'django.contrib.auth.context_processors.auth', 
               'django.contrib.messages.context_processors.messages', 
           ], 
       }, 
   }, 
] 

WSGI_APPLICATION = 'myproject.wsgi.application' 


DATABASES = { 
   'default': { #change: my database setup
       'ENGINE': 'django.db.backends.mysql', 
       'NAME': 'mydb1', 
       'USER': 'myuseruser', 
       'PASSWORD': 'my_db_password', 
       'HOST': '192.168.0.2', 
       'OPTIONS': { 
           'read_default_file': '/etc/my.cnf.d/client.cnf', 
           'init_command': "SET sql_mode='STRICT_TRANS_TABLES'; SET SESSION binlog_format = 'ROW';", 
       },
        'jgmotordb': { #delete: my database setup
       'ENGINE': 'django.db.backends.mysql', 
       'NAME': 'mydb2', 
       'USER': 'myuseruser', 
       'PASSWORD': 'my_db_password', 
       'HOST': '192.168.0.2', 
       'OPTIONS': { 
           'read_default_file': '/etc/my.cnf.d/client.cnf', 
           'init_command': "SET sql_mode='STRICT_TRANS_TABLES'; SET SESSION binlog_format = 'ROW';", 
           } 
       }
   } 
}

AUTH_PASSWORD_VALIDATORS = [ 
   { 
       'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 
   }, 
   { 
       'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 
   }, 
   { 
       'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 
   }, 
   { 
       'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 
   }, 
] 

LANGUAGE_CODE = 'en-us' 
TIME_ZONE = 'UTC' 
USE_I18N = True 
USE_L10N = True 
USE_TZ = True 

STATIC_URL = '/static/' # my static folder
STATICFILES_DIRS = [ 
   os.path.join(BASE_DIR, '0static'),  # my static folder (before for 'collectstatic' command)
] 
STATIC_ROOT = os.path.join(BASE_DIR, 'static') 
AUTHENTICATION_BACKENDS = ( 'myproject.backend.custombackend', ) #delete: my custom backends

It’s my django project. Therefor, you might find my setup is not ideal, but it works! 🙂 (and it took me a week to make it works).

I learn that, most of tutorials use aptapt-get for installation. Since I use CenOS (which use yum as default) I find it annoying. 😦

Please leave a comment for any suggestion or if you find this post helpful.

Iklan

School of Life Called ‘Marriage’

If you marry the right person, everyday is Valentine’s Day.
Marry the wrong person, everyday is Martyrs Day.
Marry a lazy person, everyday is Labour Day.
Marry a rich person everyday is New Year’s Day
Marry an immature person, everyday would seem like Children’s Day.
Marry a cheater or liar, everyday will become April Fool’s Day.
And if you don’t get married, everyday is Independence Day!
Marriage is the only school where you get the Certificate before you start.

It’s also a school where you will never graduate.
It’s a school without a break or a free period.
It’s a school where no one is allowed to drop out.
It’s a school you will have to attend every day of your life.
It’s a school where there is no sick leave or holidays.

It’s a school founded by God:

  1. On the foundation of love.
  2. The walls are made out of trust.
  3. The door made out of acceptance.
  4. The windows made out of understanding
  5. The furniture made out of blessings
  6. The roof made out of faith.

Be reminded that you are just a student not the principal.
God is the only Principal.
Even in times of storms, don’t be unwise and run outside.
Keep in mind that, this school is the safest place to be.

Never go to sleep before completing your assignments for the day.
Never forget the C-word…Communicate.
Communicate with your classmate and with the Principal.

If you find out something in your classmate (spouse) that you do not appreciate,
Remember your classmate is also just a student not a graduate, God is not finished with him/her yet. So take it as a challenge and work on it together.

Do not forget to study the Holy Book (the main textbook of this school). Start each day with a sacred assembly and end it the same way. Sometimes you will feel like not attending classes, yet you have to. When tempted to quit find courage and continue. Some tests and exams may be tough but remember, the Principal knows how much you can bear and yet it’s a school better than any other.

It’s one of the best schools on earth; joy, peace and happiness accompany each lesson of the day. Different subjects are offered in this school, yet love is the major subject. After all the years of theorizing about it, now you have a chance to practice it. To be loved is a good thing, but to love is the greatest privilege of them all.

Marriage is a place of love, so love your spouse. More grace from God.

Share this to all your married friends to encourage them and to your unmarried friends to counsel and educate them.

Coding Wisdom #1

  1. If it’s not tested, it doesn’t work.
  2. Source control is your friend – make sure you use it.
  3. Just because you wrote it doesn’t mean you own it — don’t be offended if someone else on your team has to change your code.
  4. Don’t reinvent the wheel, library code is there to help.
  5. The fastest code is code that’s never executed — look for early outs.
  6. Just because you didn’t write it doesn’t mean it’s crap.
  7. Source code is just a hint to the compiler about what you want to do, it won’t necessarily do it (e.g. You might declare a function as inline but the compiler doesn’t have to obey).
  8. Code that’s hard to understand is hard to maintain.
  9. Code that’s hard to maintain is next to useless.
  10. “Whilst I’m editing this file I’ll just…” is a great way to introduce feature creep and bugs.
  11. The neater your code layout, the easier it is to read. The easier it is to read, the easier it is to understand and maintain.
  12. Code is not self documenting. Help others by adding comments to guide them. You may understand it now but what about in 5 years time?
  13. Bad Code can and will come back to haunt you.
  14. There is no such thing as a 5 minute job. It’ll always take at least half a day.
  15. Magic numbers are bad.
  16. Constants don’t take up storage, they’re compile time text substitutions.
  17. Project management will always want you to do twice as much in half the time.
  18. If there is a bug, the user will find it.
  19. A code review is not a criticism.
  20. It’s not the quantity of code that matters, it’s the quality. Any idiot can bang out 40k line of code but that doesn’t make it fit for purpose.
  21. The true cost of poorly written code is in the maintenance.
  22. Eat your own dog food — fixing bugs in your own code helps you code better and improves your understanding.
  23. Code rots over time.
  24. If the user didn’t ask for a feature, don’t add it.
  25. If it’s not tested, it doesn’t work (yes, I know I’ve included that twice but it’s really important)

Quoted from: Drew Eckhardt @ What are some of the most basic things every programmer should know?