使用Docker简化离线Python部署

发布于:2021-01-20 11:27:02

0

819

0

devops docker python

如果生产服务器不能访问Internet或内部网络,则需要将Python依赖项(作为轮文件)和解释器与源代码捆绑在一起。

本文将介绍如何打包一个Python项目,以便在一台使用Docker与Internet断开连接的机器上进行内部分发。

目标

在这篇文章的结尾,您将能够……

  1. 描述Python wheels和egg之间的区别

  2. 说明为什么您可能要在Docker容器中构建Python wheel文件

  3. 启动自定义环境以使用Docker构建Python wheels

  4. 将Python项目捆绑并部署到无需访问Internet的环境

  5. 解释如何将该部署设置视为不变的

场景

这篇文章的起源来自一个场景,在这个场景中,由于安全原因,我不得不将一个遗留的Python 2.7 Flask应用程序分发到一个Centos 5盒子中,而这个盒子无法访问Internet。

Python wheels(而不是eggs)是这里的方法。

Python wheels文件与eggs类似,因为它们都是只是用来分发代码的zip文件。wheels的不同之处在于它们是可安装的,但不是可执行的。它们也是预编译的,这样用户就不用自己构建包了;因此,加快了安装过程。可以将它们看作是Python eggs的更轻的预编译版本。它们特别适合于需要编译的包,如lxml或NumPy。

这样,wheels应该建立在运行它们的相同环境上,因此,使用多个版本的Python跨多个平台构建它们可能是一个巨大的难题。

这就是Docker发挥作用的地方。

Bundle

在开始之前,需要注意的是,我们将使用Docker简单地启动一个构建wheels的环境。换句话说,我们将使用Docker作为构建工具,而不是部署环境。

此外,请记住,此过程不仅适用于旧版应用程序,还可用于任何Python应用程序。

堆栈:

  • OS: Centos 5.11

  • Python version: 2.7

  • App: Flask

  • WSGI: gunicorn

  • Web server: Nginx

环境设置

我们将在本节中通过网络下载和安装依赖项。假设您通常不需要设置服务器本身;它应该已经预先配置好了。

由于控制盘是在Centos 5.11环境下构建的,因此几乎可以在任何Linux环境下工作。因此,如果您想继续,请使用最新版本的Centos启动一个Digital Ocean droplet。

SSH into the box,作为root用户,在继续本教程之前,请添加安装Python所需的依赖项:

$ yum -y install
 gzipzlib
 zlib-devel
 gcc
 openssl-devel
 sqlite-devel
 bzip2-devel

接下来,安装并运行Nginx:

$ yum -y install
   epel-release
   nginx
$ sudo /etc/init.d/nginx start

在浏览器中导航到服务器的IP地址。您应该看到默认的Nginx测试页面。

接下来,更新/etc/Nginx/conf.d中的Nginx配置/默认.conf要重定向流量:

server {  
   listen 80;
   listen [::]:80;
   location / {
       proxy_pass http://127.0.0.1:1337;    
   }
}

重新启动Nginx:

$ service nginx restart

现在您应该在浏览器中看到502错误。

在框中创建常规用户:

$ useradd$ passwd

退出完成后的环境。

部署

要部署,首先通过tarball和安装脚本手动保护副本,setup.sh,到远程框:

$ scp app-v20180119.tar.gz@:/home/$ scp setup.sh@:/home/

快速查看安装脚本:

#!/bin/bash

USAGE_STRING="USAGE: sh setup.sh {VERSION} {USERNAME}"

VERSION=$1
if [ -z "${VERSION}" ]; then
   echo "ERROR: Need a version number!" >&2
   echo "${USAGE_STRING}" >&2
   exit 1
fi

USERNAME=$2
if [ -z "${USERNAME}" ]; then
 echo "ERROR: Need a username!" >&2
 echo "${USAGE_STRING}" >&2
 exit 1
fi

FILENAME="app-v${VERSION}"
TARBALL="app-v${VERSION}.tar.gz"

# Untar the tarball
tar xvxf ${TARBALL}
cd $FILENAME

# Install python
tar xvxf Python-2.7.14.tar.xz
cd Python-2.7.14
./configure
   --prefix=/home/$USERNAME/python2.7
   --with-zlib-dir=/home/$USERNAME/lib
   --enable-optimizations
echo "Running MAKE =================================="
make
echo "Running MAKE INSTALL ==================================="
make install
echo "cd USERNAME/FILENAME ==================================="
cd /home/$USERNAME/$FILENAME

# Install pip and virtualenv
echo "python get-pip.py  ==================================="
/home/$USERNAME/python2.7/bin/python get-pip.py
echo "python -m pip install virtualenv  ==================================="
/home/$USERNAME/python2.7/bin/python -m pip install virtualenv

# Create and activate a new virtualenv
echo "virtualenv venv  ==================================="
/home/$USERNAME/python2.7/bin/virtualenv venv
echo "source activate  ==================================="
source venv/bin/activate

# Install python dependencies
echo "install wheels  ==================================="
pip install wheels/*

这应该相当简单:这个脚本只是设置一个新的Python环境和在新的虚拟环境中安装依赖项。

将SSH放入框中并运行安装脚本:

$ ssh@$ sh setup.sh 20180119

这将需要几分钟。完成后,cd进入app目录并激活虚拟环境:

$ cd app-v20180119
$ source venv/bin/activate

运行测试:

$ python test.py

完成后,启动gunicorn作为守护程序:

$ gunicorn -D -b 0.0.0.0:1337 app:app

结论

在本文中,我们研究了如何打包一个带有Docker和Pythonwheels的Python项目,以便在与Internet断开的机器上部署。

通过这种设置,由于我们打包了代码、依赖项和解释器,我们的部署被认为是不可变的。对于每个新部署,我们将启动一个新环境,并在关闭旧环境之前进行测试以确保其正常工作。这将消除继续在遗留代码之上部署时可能出现的任何错误或问题。另外,如果您发现了新部署的问题,您可以轻松回滚。