Python Playground Part 2: Deploying Flask app on Ubuntu (nginx, uwsgi, supervisor, git)
14 Sep 2012
Tags:
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
$ sudo apt-get install -y python-software-properties python-dev python-pip
$ sudo pip install virtualenv
NoImageYet also requires Python Imaging Library , which depends on certain native libs. Here it goes:
$ 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/
Installing NGINX
$ 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}
Installing Git, Supervisord and uWSGI
$ 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
Creating Deploy / App user
You might want to change password from password
to something more applicable ;)
$ 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
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 usage / Deploying
$ cd /home/deploy
$ sudo -u deploy wget "https://raw.github.com/gist/3667663/create_project.sh"
$ sudo -u deploy chmod +x create_project.sh
Login as deploy user, e.g. su - deploy
Executing the script.
Parameters: app name (theservice
) and service domain name (yourdomain.com
)
$ ./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://[email protected] /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!
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.
# theservice.py file
#...
app = flask . Flask ( __name__ )
#...
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 ..)
# 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
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
$ 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(+)
[email protected] '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://[email protected] /home/deploy/repo/noimageyet
c76aa28..cd59843 live -> live
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
Profit
http://knowyourmeme.com/memes/profit
NB. If you've found typos or errors, please
suggest a correction
or
edit on github .