By the end of this post, you will be able to deploy your local code to any number of remote servers with a single command. This assumes, of course, that you have configured your web server with uWSGI to host your Flask website and you have shell access to this server. It is encouraged that prior to proceeding you at least understand hosting a Flask site, otherwise a lot of this might not make sense, as most details relating to hosting are omitted here (particularly the idiosyncrasies of of using a virtualenv in your hosting environment).
If you do not have shell access to your web server, maybe someone else can help. Maybe you need to check out the myriad of cloud hosting services out there (e.g. Amazon Web Services, which I use to host this blog, among other sites) and make the jump. You will learn a lot more this way and be able to do much more interesting things!
So, we have a little Flask website that we wish to be able to develop locally and then later deploy to our live (perhaps production) site.
First, locally, we should install Fabric, this can be in a virtual environment or…
|
1 |
~# sudo pip install fabric |
Well, let’s assume that we have a Flask site, example_site, we’re going to first require a setup.py.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/usr/bin/env python from setuptools import setup setup( name='example_site', version='0.1', long_description=__doc__, packages=['example_site'], include_package_data=True, zip_safe=False, install_requires=['Flask'] ) |
What we’re doing above is saying that our Flask site, example_site, is a package in a directory with the same name. We define our requirements, package name, etc. here.
After we have a nice setup file, we can start to script what’s called our fabfile. We must define two actions for the fabfile, a pack and a deploy function.
pack() defines how to ball up our sources.
deploy() defines how to push it to the server and what to do once our sources are there.
I chose to configure my fabfile like below, however the Fabric documentation offers the whole suite of features that are available to you.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#!/usr/bin/env python from fabric.api import * # Configure user, private key, etc. for SFTP deployment env.user = 'ec2-user' env.hosts = ['example.com'] env.keyfile = ['$HOME/.ssh/example_rsa'] def pack(): local('python setup.py sdist --formats=gztar', capture=False) def deploy(): dist = local('python setup.py --fullname', capture=True).strip() put('dist/%s.tar.gz' % dist, '/tmp/example_site.tar.gz') # now we're on the remote host from here on out! run('mkdir /tmp/example_site') with cd('/tmp/example_site'): run('tar zxf /tmp/example_site.tar.gz') run('mv ' + dist + '/* .') sudo('/var/www/example_site/venv/bin/python setup.py install') sudo('chown -R nginx:nginx /var/www/example_site') sudo('rm -rf /tmp/example_site /tmp/example_site.tar.gz') # alert uWSGI to reload the project sudo('touch /var/www/example_site.wsgi') |
Once we are satisfied that our deploy scripts look good, we are ready to rock!
We can execute our pack and deploy in a single command:
|
1 |
~# fab pack deploy |
That’s it! Fabric will then ball up your sources, upload them to your remote server, and execute a script that handles those sources on the remote end. Once this is configured properly, developing is bliss–no matter what solution you choose, Fabric or otherwise, easy deployment of local code is incredibly important for your web project.
It allows you to focus on code and not operations (that are repeatable and trivial).
