By Tonino Jankov, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud's incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.
Flask is a minimalistic and modular web framework written in Python. It initially started as an April fools joke by Armin Ronacher, about python micro frameworks in 2010, but then it took a life of its own, becoming one of the most widely adopted python frameworks - most popular on GitHub in 2016.
It started, basically as a 160 lines of code thrown together to create a very basic WSGI application. Its built on two foundational libraries - Werkzeug, which is a wsgi / http utility library (or middleware, if you will) - and Jinja2 - fast python templating engine.
The whole flask stack is BSD licensed.
Alibaba Cloud Elastic Compute Service (ECS) is a flexible cloud product that allows us to deploy many different server technologies on a scalable, secure and easy to use platform. In this guide, we will be installing Flask and running a sample application on an Alibaba Cloud ECS instance with Ubuntu 16.04.
For the purpose of this guide, we will setup an ECS instance with Ubuntu 16.04 LTS. The procedure itself is pretty straightforward - after we log into Alibaba Cloud web management console, we select Elastic Compute Service in the leftmost main menu, and choose Instances in the sub-menu. We will then be able to start the process of creating new instance by clicking the Create Instance button in the top-right corner of the screen.
In the process, we will choose Ubuntu 16.04 LTS image, and select security enhancements option - this includes intrusion detection, brute-force login protection, email alerts, etc.
After we specify all the options, we proceed with our instance creation. After about 5 minutes, we should be able to see our instance public ('internet') IP, which allows us to login to our server via ssh using access details we specified at creation (either key or password access).
Provided that we created our instance successfully, we will connect to it's public IP, and update repositories and, optionally, upgrade the system: apt-get update && apt-get upgrade
. If we have logged in as root, we don't need to use sudo
.
Flask docs recommend that we use the latest version of Python, which is 3.7.0, but the default version shipped with Ubuntu is 2.7 - so we will fix this. Instead of removing the 2.7 and reinstalling 3.7.0 version, we will use pyenv
. Pyenv is python version manager, and it will allow us to install and use any version of python. To install pyenv
, we will first install git
and curl
as prerequisites: apt-get install git curl -y
. Now we can use the following one-liner to install pyenv
:
curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
Pyenv
will warn us, upon installation, to add following lines to ~/.bash_profile
if we haven't done it yet:
export PATH="/root/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
(we will create the file if it doesn't exist yet) - and when we add it, instead of logging out and logging back in to restart the shell session, we will source ~/.bash_profile
to load our new command. Now we will install dependencies for building our version of python (and other things):
apt-get install build-essential python-dev python-setuptools python-pip python-smbus libncursesw5-dev libgdbm-dev libc6-dev zlib1g-dev libsqlite3-dev tk-dev libssl-dev openssl libffi-dev zlib1g-dev libbz2-dev
libreadline-dev -y
The python-pip
package will make the pip
command available, in case it is missing - this is the default python package manager.
To list all python versions available in pyenv for installation, we use pyenv install -l
- but this will throw out an unwieldy list of versions, so we will pipe it to grep
- a notorious linux utility, to filter output to exactly what we need:
pyenv install -l | grep 3.7
This shows us all the versions containing "3.7" - and we continue installing version 3.7.0 - pyenv install 3.7.0
After python 3.7.0 is installed, we make it the default global version:
pyenv global 3.7.0
We can check the current version with pyenv version
We install flask by issuing command pip install Flask
. Next thing we do is create a minimal Flask Hello World app. We will create a directory to contain our app under /var/www:
cd /var/www
mkdir flaskapp
And then we put the following code in app.py
file in that directory:
python
from flask import Flask
application = Flask(__name__)
@application.route('/')
def hello_world():
return 'Hello World!'
For the purpose of deployment, we also install uwsgi
- which is a server interface software that enables servers like NGINX to serve python applications:
pip install uwsgi
We also, obviously, install nginx:
sudo apt-get install nginx -y
Now that the nginx is installed, we will add our virtual host file in /etc/ngind/sites-enabled/
- and remove the default
virtual host that is created when we install nginx. We add following into our somedomain
file:
nginx
# the upstream component nginx needs to connect to
upstream flask {
server unix:///tmp/flaskapp.sock;
}
# configuration of the server
server {
# the port your site will be served on
listen 80;
# the domain name it will serve for
server_name myxydomain.com; # substitute with your domain name
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass flask;
include /var/www/flaskapp/uwsgi_params; # the uwsgi_params file you installed
}
}
Here we will replace the myxydomain.com
in the code with the actual name of our domain, whose domain records we have directed to the public IP address of our ECS server instance.
Nginx virtual host file here is referring to uwsgi_params
file - we will simply download this file from nginx github repo - it describes how to pass request parameters from nginx to uwsgi. We put this file in our flaskapp
directory
Now if we restart nginx after we create virtual host - service nginx restart
- and start uwsgi on the defined socket, like
uwsgi --socket /tmp/flaskapp.sock --wsgi-file /var/www/flaskapp/flaskapp.py --chown-socket=www-data:www-data --logto /var/log/uwsga.log
- we should see the result "Hello World!!!" in our browser when we load our website url.
This way we can debug our uwsgi setup before installing it as a service. We change owner of the socket file on every start, because of permission issues, and we output all logging to a designated file under /var/log
. Our basic Hello World app is being served by nginx, which passes requests to our python application through uwsgi.
If this step succeeded, we can proceed with setting up our flask app as a service.
First thing we will do is to put our runtime settings for uwsgi into an ini file:
bash
[uwsgi]
chdir = /var/www/flaskapp
module = flaskapp
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10
# the socket (use the full path to be safe)
socket = /tmp/flaskapp.sock
# ... with appropriate permissions - may be needed
# chmod-socket = 664
chown-socket = www-data:www-data
daemonize = /var/log/uwsgi.log
vacuum = true
Here we added master / worker processes, daemonize instead of logto, and some other details that may come handy, like the commented chmod line in case we have problems with permissions.
Now, the next thing we do is to, again, test these settings on a command line, running uwsgi behind nginx:
uwsgi --ini /var/www/flaskapp/uwsgi.ini
- we don't need to pass any other parameters to uwsgi, because all the parameters are in our new ini file (for the simplicity sake, we put it into /var/www/flaskapp
directory, but normally it would probably be under /etc/uwsgi
or something like that).
Now if we get back "Hello World!" in our browser, that means we succeeded.
To make sure that our app will be up even upon the server restart, we will add the startup script to our rc.local
.
First thing we do is make uwsgi
available globally, because, currently, we created it under root
account, using pyenv, and whereis uwsgi
shows us that it is at /root/.pyenv/shims/uwsgi
. As a precaution against possible issues, we create a global link to it:
ln -T /root/.pyenv/shims/uwsgi /usr/local/bin/uwsgi
Then we put the startup script into /etc/rc.local
, just before the exit 0
line:
bash
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
/usr/local/bin/uwsgi --ini /var/www/flaskapp/uwsgi.ini
exit 0
We should also make sure that the rc.local
file is executable - a sudo chmod 755 /etc/rc.local
command will do.
We can try out our startup script by simply calling it on the command line - /etc/rc.local
, and it will show us if there are any issues. uwsgi
logs are in /var/log/uwsgi.log
, so if there are any issues with flask or uwsgi, that file should give us clues. If, however, we encounter issues with nginx, like those generic nginx error pages with codes like 503, /var/log/nginx/error.log
holds latest nginx errors, so we can draw some conclusions from there.
Finally, if everything went well, we will reboot the server, and after couple of seconds, we should be able to see Hello World!
in our browser - meaning that our setup was successful.
In this guide we have covered the setup and deployment of a Flask application to Alibaba Cloud Elastic Compute Service (ECS) instance, addressing potential issues along the way. Real, production setup will also, probably, use more subtleties and features of both Nginx (caching, for example), and Flask, and possibly SSL encryption, but this is, hopefully, a useful starting point.
Real-time SQL Server Migration to Alibaba Cloud ApsaraDB RDS for SQL Server
How China Is Different (Part 2) – Cloud Infrastructure Networking
2,599 posts | 758 followers
FollowAlibaba Clouder - October 19, 2018
Alibaba Cloud Community - January 10, 2022
Alibaba Clouder - December 17, 2018
Alibaba Clouder - March 12, 2019
Farruh - May 12, 2023
Alibaba Clouder - April 26, 2019
2,599 posts | 758 followers
FollowElastic and secure virtual cloud servers to cater all your cloud hosting needs.
Learn MoreOver 20 million domain, free WHOIS privacy protection.
Learn MoreMarketplace is an online market for users to search and quickly use the software as image for Alibaba Cloud products.
Learn MoreMore Posts by Alibaba Clouder
Arman Ali May 26, 2021 at 8:41 am
Great!