Monday, June 15, 2015

Docker based Python Project Deployment with NginX, Supervisor, uwsgi on Ubuntu

For Docker installation refer : https://docs.docker.com/installation/ubuntulinux/

Assume your python code is inside /var/app/project/ and server run file is start.py



Note : Create folder/path if don't exists. for example /var/app/run/ which don't exits then create it. similarly for other paths.

Step 1 :

Create one custom supervisord.conf file inside /var/app/supervisor/

Content of file should be :


[unix_http_server]
file=/var/app/run/supervisor.sock
[supervisord]
logfile=/var/app/log/supervisord.log
loglevel=info
pidfile=/var/app/run/supervisord.pid
nodaemon=true
childlogdir=/lib/app/log/supervisor
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/app/run/supervisor.sock
[include]
files = /var/app/supervisor/conf.d/*.conf

Step 2 :

Create "superisor.docker.conf" file inside /var/app/supervisor/conf.d/

Content of file should be :


[program:pyenv]
command = /usr/bin/docker run --rm --name pyenv -v /var/app:/var/app felixonmars/archlinux supervisord -c /var/app/supervisor/supervisord.conf

Step 3 :

make link of file /var/app/supervisor/conf.d/superisor.docker.conf in /etc/supervisor/conf.d/ using :


sudo ln -s /var/app/supervisor/conf.d/superisor.docker.conf /etc/supervisor/conf.d/

Step 4 :

Now onwards , your all supervisor .conf files will be inside /var/app/supervisor/conf.d/

Create project_supervisor_docker.conf file inside /var/app/supervisor/conf.d/ and its content should be :


[program:project]
command = /usr/bin/uwsgi --plugin=python2
    --limit-as=512 --processes=2 --max-request=2000
    --memory-report --enable-threads
    --socket=/var/app/run/uwsgi/project.socket
    --stats=/var/app/run/uwsgi/project.stats
    --logto=/var/app/log/uwsgi/project.log
    --pidfile=/var/app/run/uwsgi/project.pid
    --master --no-orphans --logdate --chmod-socket=660
    --uid=33 --gid=33 --need-app
    --wsgi-file=/var/app/project/start.py
stopsignal=INT

Step 5 :

Create project_master_supervisor_docker.conf inside /var/app/supervisor/conf.d/ and its content :


[program:project_master]
command = /usr/bin/python2 start.py
directory=/var/app/project

Step 6 :

Create Nginx Configuration file for project. Its content should be :

 

upstream push_daemon_project {
    server 127.0.0.1:8284; #Assume push socket on port 8284
}

server {
    listen 80;
    listen [::]:80;

    server_name project.com www.project.com;

    location = /nginx_stub_status {
        stub_status on;
        allow 127.0.0.1;
        deny all;
    }

    location / {
        return 301 https://project.com$request_uri;
    }
}

server {
    listen 443 ssl spdy;
    listen [::]:443 ssl spdy;

    ssl_certificate /var/app/cert/project.com.crt; # certificate ssl
    ssl_certificate_key /var/app/cert/project.com.key; # certificate key ssl

    server_name project.com www.project.com;
    access_log /var/log/nginx/project.access.log;
    error_log /var/log/nginx/project.error.log;

    root /var/app/project/web;  ## template (html) directory

    location /static {
        alias /var/app/project/static;  ## static files
    }

    location = /nginx_stub_status {
        stub_status on;
        allow 127.0.0.1;
        deny all;
    }

    location /websocket {
        proxy_pass http://push_daemon_project;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location / {
        include uwsgi_params;
        uwsgi_pass unix:///var/app/run/uwsgi/project.socket;
    }
}

Step 7 :

Restart all instances :


sudo chown -R www-data:www-data /var/app/project
sudo service nginx restart
sudo supervisorctl update
sudo /etc/init.d/supervisor force-reload
sudo docker ps -a # you can see docker process id : for ex : 6a2dfdeb0000
sudo docker restart 6a2dfdeb0000


Grunt , bower, nodejs installation & commands

 

sudo apt-get install --reinstall --install-recommends nodejs
sudo npm install -g grunt
sudo npm install -g grunt-cli
sudo npm install -g bower

# Locate package.json and run : 
 sudo npm install
 
# Locate bower.json and run :
 bower install

# Locate .Gruntfile.js and run : 
 "grunt dev --force" in local
 "grunt build --force" in live