How To Deploy your Flask Application On Offline Servers

Recently, we had to migrate our 22 Flask micro-services to new servers.
As automatic deployment was implemented for all of these, we thought it would be done in a glimpse.
What a surprise when we connected to the servers and realized that they were totally isolated from the internet!

No git clone, no git submodule update, no pip install, even virtualenv was failing…
So we rolled up our sleeves and iterated to create a new automated process.

Dealing with pip packages

Our first attempt was to commit our entire virtualenv, like we would do with the node_modules in a Node.js app.
The issue with this method is that the paths in the bin/activate are hard coded, which brought errors when using it.

We then decided to download our pip packages without installing them to realize an offline installation directly on the server.
Using a requirements file, we simply used the download options of pip:

pip download -r requirements.txt -d <PATH_FOR_PACKAGES>

We then zipped our source code (including our git submodules) to send it on the server through a ftp connection.

Setting up virtualenv

After that, we had to set our virtualenv.
Its default behaviour is to download preinstalled packages (pip, setuptools and wheels) from the internet.
We set the --no-download option to prevent this to happen.
As our app was using Python3 and the default version was Python2, we had to precise its path to virtualenv:

virtualenv --no-download venv -p <PATH_TO_PYTHON_3>

We were then able to install our dependencies using the committed packages!

pip3 install --no-index --find-links pip_installs/ -r requirements.txt

Tougher packages

Some python packages (like pandas) are downloading other packages themselves during their installation.
We were able to bypass this problem installing the required packages before.

For example, Pandas was downloading Cython and numpy during its installation:

pip3 install Cython==0.25.1 --no-index --find-links pip_installs/
pip3 install numpy==1.11.2 --no-index --find-links pip_installs/
pip3 install --no-index --find-links pip_installs/ -r requirements.txt

I hope this article will help people in a similar situation, please feel free to give feedback!