Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
195 lines (141 sloc) 6.77 KB
title date permalink layout tags
Python Playground Part 2: Deploying Flask app on Ubuntu (nginx, uwsgi, supervisor, git)
2012-09-14
2012/09/python-playground-part-2-deploying-flask-app-on-ubuntu-nginx-uwsgi-supervisor-git/
post
python
mvp
devops
git

This is a followup on my previous post on building and getting up and running small online image placeholder generator service - https://noimageyet.com.

This post will list steps to set up a Flask app in Ubuntu Linux server 12.04 using nginx, uWSGI and supervisord. On top of that I will provide installation scripts and deployment scheme using Git SCM.

Credits First

This post (and service deployement in live) would not be possible without these awesome resources:

[1] Conrad Kramer's "Getting a Flask website up and running in Ubuntu"

[2] Conrad Kramer's "Deploy a website using git in Ubuntu"

[3] Linode StackScript: shazow's stack (nginx+uwsgi+postgresql+more)


Installing Python stack

{% highlight console %} $ sudo apt-get install -y python-software-properties python-dev python-pip $ sudo pip install virtualenv {% endhighlight %}

NoImageYet also requires Python Imaging Library, which depends on certain native libs. Here it goes:

{% highlight console %} $ sudo apt-get install -y libfreetype6-dev libjpeg62-dev libpng12-dev

PIL PIP package fails to install, since it expects libs located in /usr/lib/

So, will reset /usr/lib/ *.so references

$ sudo rm -rf /usr/lib/{libfreetype.so,libz.so,libjpeg.so} $ sudo ln -s /usr/lib/*-linux-gnu/{libfreetype.so,libz.so,libjpeg.so} /usr/lib/ {% endhighlight %}

Installing NGINX

{% highlight console %} $ sudo apt-get install -y nginx

Nginx-related: Move the default nginx config name so that it doesn't take

priority over our other configurations.

$ sudo mv /etc/nginx/sites-enabled/{default,99_default} {% endhighlight %}

Installing Git, Supervisord and uWSGI

{% highlight console %} $ sudo apt-get install -y build-essential git-core

$ sudo apt-get install -y supervisor $ sudo apt-get install -y uwsgi uwsgi-plugin-python python-uwsgidecorators {% endhighlight %}

Creating Deploy / App user

You might want to change password from password to something more applicable ;)

{% highlight console %} $ sudo adduser --disabled-password --gecos "" deploy

$ sudo passwd deploy <<EOF password password EOF

echo "Adding deploy user to sudoers" sudo tee -a /etc/sudoers <<EOF deploy ALL=(ALL) NOPASSWD:ALL EOF {% endhighlight %}

Auto-magic deploy script

The script below is derived from [3].

Script summary: scipt creates folder layout, configures NGINX site, updates supervisod config and setups Git repository with post-receive hook to perform re-deploy on push magic.

Script

<script src="https://gist.github.com/3667663.js?file=create_project.sh"></script>

Script usage / Deploying

  • Get the script.

{% highlight console %} $ cd /home/deploy $ sudo -u deploy wget "https://raw.github.com/gist/3667663/create_project.sh" $ sudo -u deploy chmod +x create_project.sh {% endhighlight %}

  • Login as deploy user, e.g. su - deploy
  • Executing the script. Parameters: app name (theservice) and service domain name (yourdomain.com)

{% highlight console %} $ ./create_project.sh theservice yourdomain.com This script is intended to be run on a remote server, not on a local development environment. It will create a bunch of directories and change a bunch of configurations. Are you sure you want to continue? [y/N] y ... Setup your development clone as follows:

 git branch live
 git remote add -t live live ssh://deploy@192.168.1.103/home/deploy/repo/theservice

Now you can deploy:

 git checkout live
 git merge master
 git checkout master
 git push live

Or use this handy 'deploy' alias in your ~/.gitconfig file:

 deploy = "!merge(){ git checkout $2 && git merge $1 && git push $2 && git checkout ${1#refs/heads/}; }; merge $(git symbolic-ref HEAD) $1"

So you can do (from 'master'):

 git deploy live

Happy pushing! {% endhighlight %} Please follow the script instructions. When pushing please note: the script assumes folder layout is theservice/theservice.py and theservice.py exports Flask application as app. E.g.

{% highlight python %}

theservice.py file

#... app = flask.Flask(name) #... {% endhighlight %}

  • When application code has been pushed to server (following script recomendations) you should resolce app's dependecies and do proper app's configuration (db connections, etc ..)

{% highlight console %}

this will install app dependencies

$ source ~/env/noimageyet/local/bin/activate

usual way to provide/install dependencies

$ pip install -r deploy/theservice/requirements.txt

restart services

$ sudo service nginx restart

supervisor sometimes fails to reload via restart

$ sudo service supervisor stop $ sleep 3 $ sudo service supervisor start {% endhighlight %}

Vuala part

We are done. Your service should be available at http://youdomain.com and http://www.youdomain.com.

Deploy part should be as easy as sample below

{% highlight console %} $ git add noimageyet.py && git commit -m 'the change' [master df78831] the change 1 file changed, 1 insertion(+) $ git deploy live Switched to branch 'live' Auto-merging noimageyet.py Merge made by the 'recursive' strategy. noimageyet.py | 1 + 1 file changed, 1 insertion(+) deploy@noimageyet.com's password: Counting objects: 10, done. Delta compression using up to 4 threads. Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 625 bytes, done. Total 6 (delta 4), reused 0 (delta 0) remote: From /home/deploy/repo/noimageyet remote: * branch live -> FETCH_HEAD remote: Restarting uwsgi. To ssh://deploy@noimageyet.com/home/deploy/repo/noimageyet c76aa28..cd59843 live -> live Switched to branch 'master' Your branch is ahead of 'origin/master' by 1 commit. {% endhighlight %}

Profit

http://knowyourmeme.com/memes/profit