Deploying Python Web App to Alibaba ECS with Fabric

tyaakow

tyaakow

Posted on June 22, 2020

Deploying Python Web App to Alibaba ECS with Fabric

Fabric is a Python library used to streamline and automate ssh workflows. It can be very useful in automating and scripting tedious, repetitive or complex tasks, deployments, installations and configurations on remote servers.

In this article we introduce Fabric, and show how to automate deployment of a Flask web app to Alibaba Cloud Elastic Compute Service.

Fabric - the introduction

Fabric is a tool which we can use to deploy or sync our local projects to remote server. We can also automate all operations we can achieve through SSH - we can configure our server, install or update our software stack, start, stop, update or restart our application.

This article presumes that the reader already created and configured a server on Alibaba Cloud to serve a Flask web app, and that it is operational.

In this blog post we can find a full guide to set up Ubuntu server on Alibaba ECS to serve a Flask app. If we follow this guide, our app will live under /var/www/flaskapp (we will use flaskapp for the directory name here, but it can be changed to anything else).

According to the linked guide, our flaskapp will contain two files - uwsgi.ini and app.py.

Deployment Setup

App.py file will contain something basic, like this:

 from flask import Flask
  application = Flask(__name__)

  @application.route('/')
  def hello_world():
      return 'Hello World!'

Now, to streamline our deployment, we will presume the same document structure both on our local development machine and on the server. We also presume that on our local machine we are using bash command line or something similar - on MS Windows we will use WSL shell.

If we start our (very basic) app locally, by doing flask run in our flaskapp directory, we will get a simple Hello World! web page on our localhost:

hello world!

Now we need to install fabric - we need only to install it locally, our production or development servers don't need anything installed:

pip install fabric

Depending on the OS we are running, we may also be able to install it with

sudo apt-get install fabric

Fabric dependencies are the Python versions 2.7 or 3.4+; Invoke task-execution library;
and Parmiko SSH library. Once we install fabric, we should be able to run the fab command in our terminal:

Fab Command

As we can see, fab command will immediately complain about the (lack of) presence of the fabfile in the current directory, which should contain configuration and instructions for fabric to run its commands.

We will cd into the parent directory of our flaskapp project, and create our fabfile . Fabfile is a simple python file with some imports, variables, and function definitions:

import sys
from fabric2 import Connection, task
from fabric2.config import Config

PROJECT_NAME = "fabtut"
REMOTE_PATH = "/var/www/flaskapp"
LOCAL_PATH = "/var/www/flaskapp"


def get_connection(ctx):
    try:
        with Connection(ctx.host, ctx.user, connect_kwargs=ctx.connect_kwargs) as conn:
            return conn
    except Exception as e:
        return None


@task
def staging(ctx):
    ctx.user = "root"
    ctx.host = "xxx.xxx.xxx.xxx"
    ctx.connect_kwargs.key_filename = "/home/user/.ssh/id_rsa"

@task
def production(ctx):
    ctx.user = "root"
    ctx.host = "yyy.yyy.yyy.yyy"
    ctx.connect_kwargs.key_filename = "/home/user/.ssh/id_rsa_2"


@task
def push(ctx):
    ctx.run("rsync -avzh --exclude '.git' -e 'ssh -i {}' {}/ {}@{}:{}/".format(ctx.connect_kwargs.key_filename, LOCAL_PATH, ctx.user, ctx.host, REMOTE_PATH))

@task
def pull(ctx):
    ctx.run("rsync -avzh -e 'ssh -i {}' {}@{}:{}/ {}/".format(ctx.connect_kwargs.key_filename, ctx.user, ctx.host, REMOTE_PATH, LOCAL_PATH))

Once we save this file, in the same directory we can run fab staging push and our local flaskapp directory will be synced with the one on our staging ECS server from Alibaba.

Some Notes About the Setup

For this guide to work, our fabfile will need to contain real IP addresses in ctx.host variables in the staging and production functions.

In this fabfile example we show one of the Fabric features - we can set up multiple environments, from development to staging and production.

We can also use multiple SSH keys for multiple server environments.

This setup also demonstrates how we can chain and combine commands, so in our case we can use staging and production interchangeably and combine them with pull or push as needed.

We could also define other tasks (in the fabfile we decorate them with @task decorator), whether to preform some preliminary tasks localy or on the server, or to do some cleanup after the main task.

If we were working with Django framework, we could here define tasks to perform migrations, or, if our tasks alter the web / application server configuration, we could restart or reload the server after our task is finished.

Chaining of tasks comes handy here, and allows for defining very declarative and high-level workflows.

Since we rely on ssh authentication in this guide, we will need to have loaded our ssh public key on the ECS server. Alibaba Cloud has more documentation on how to set up SSH authentication here.

Conclusion

In this short guide, we set up Fabric deployment tool to define deployment workflows to Alibaba ECS server, and we explain how to work with Fabric. We use bash syntax combined with rsync here, but we could be using any other linux commands like awk, sed, etc.

Fabric itself allows even more declarative workflows, but we find that using linux & bash commands allows for much greater flexibility and more sophisticated workflows.

Do you have anything to add to this? Let us know in the comments.

💖 💪 🙅 🚩
tyaakow
tyaakow

Posted on June 22, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related