PYTHON October 21, 2020

使用Conda Pack打包Python独立运行时环境

Words count 6.6k Reading time 6 mins. Read count 0

版本说明:

python=2.7

Conda 的Pack工具,可以说是让我发现了新大陆。之前有个项目使用它解决了一个棘手的问题,一直没有整理相关笔记,时间长了容易淡忘,恰好有同事问我如何实现的,这里就重新整理一下。

1 棘手问题描述

简单描述一下项目中遇到的这个棘手问题:

这个项目是一个Python2.7开发的Flask服务,它里面有不少依赖需要使用pip安装,并且在网络不好的情况下容易下载失败。要求是能够让用户能够快速部署,几乎不做复杂的操作,就能够运行我们的项目,甚至是目标主机没有联网的情况下,都能够直接运行。另外是,不考虑目标主机的Linux操作系统,不管是Ubuntu还是CentOS只要是Linux,就能够保证正常运行。另外,目前大多数系统都安装了Python3的环境,我们使用的Python2环境不能够影响到已有的环境。

当时想到了一些解决方法:

  1. 编写部署脚本,自动安装依赖。这个方法虽然能能够进行快速部署,但是安装依赖,需要考虑网络,不符合需求。
  2. 使用Pyinstaller等一些工具,可以打包成可执行文件。当时觉得这个方法可行,符合需求,但是由于我们这个Flask服务,里面依赖比较多,而且比较庞大。导致使用PyInstaller打包的时候,出现各种问题,经过几天的尝试,最终我还是放弃了,因为总是出现一些莫名其妙的问题,网上一些教程都是Hello World级别的,无法参考。也可能是个人能力问题,不过我还是放弃了。

2 使用Conda Pack解决问题

下面来讲一下,如何使用Conda Pack解决问题。思路相对来说比较简单,而且是容错率较高,不会出现莫名其妙的问题。思路是这样的:

  1. 首先使用Conda创建一个Python虚拟环境
  2. 激活创建的虚拟环境
  3. 在虚拟环境中安装项目运行时的依赖
  4. 使用Pack打包运行环境
  5. 将运行环境与项目源码一块发布

Pack打包的运行环境与项目源码一块拷贝的目标主机,解压后,激活运行环境,就可以直接运行项目了。

3 Conda Pack使用

从0到1讲一下如何使用Conda Pack打包一个Flask项目运行环境。

3.1 准备环境

准备一台centos机器,配置随意,可以访问互联网。

3.1.1 安装miniconda

Miniconda是conda的免费最小安装程序。它是Anaconda的小型引导程序版本,仅包含conda,Python,它们依赖的软件包以及少量其他有用的软件包,包括pip,zlib和其他一些软件包。官网地址:https://docs.conda.io/en/latest/miniconda.html

找到对应版本,进行下载。这里选择的是Linux的Python2.7的版本。

image-20200810142732459

 curl -k -o Miniconda2-latest-Linux-x86_64.sh https://repo.anaconda.com/miniconda/Miniconda2-latest-Linux-x86_64.sh

执行下载的脚本进行安装

sh Miniconda2-latest-Linux-x86_64.sh

根据提示按回车和输入yes即可。

安装完成后重启或者source ~/.bashrc,重新加载环境变量。查看conda版本

(base) [root@172 ~]# conda -V
conda 4.8.3

3.1.2 使用conda创建Python环境

使用conda命令创建一个名字为2.7版本号为2.7的python环境。

conda create -n 2.7 python=2.7

激活环境

conda activate 2.7

这时查看python版本号:

(2.7) [root@localhost ~]# python -V
Python 2.7.18 :: Anaconda, Inc

3.2 创建一个简单的Flask项目

这里就不从头开始创建项目了,我把已经创建好的项目,发布到Git上了,直接克隆下来即可。git地址:https://github.com/shirukai/flask-with-runtime-env.git

git clone https://github.com/shirukai/flask-with-runtime-env.git

进入项目

cd flask-with-runtime-env

安装项目依赖

pip install --no-cache-dir -r requirements.txt -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

测试启动项目

python application/main.py

image-20200810194041376

3.3 打包运行环境

这里就要用到主角了:Conda Pack。官网地址:https://conda.github.io/conda-pack/。

官网文档安装Conda Pack的方法有三种,conda安装、pip包安装、pip源码安装。这里使用conda命令安装:

conda install -c conda-forge conda-pack

使用起来,也相对简单

# 该命令会将指定的名为my_env_name运行环境打包成my_env_name.tar.gz
conda pack -n my_env_name

我们也可以通过-o参数指定打包之后的名称

conda pack -n my_env_name -o out_name.tar.gz

将我们上面的2.7的环境打包

conda pack -n 2.7 -o 2.7.tar.gz

会在当前目录生成2.7.tar.gz。

创建一个名为2.7的目录

mkdir 2.7

将2.7.tar.gz解压到2.7目录下

tar -zxvf 2.7.tar.gz -C 2.7

执行如下命令激活环境

source 2.7/bin/activate

查看版本号

(2.7) [root@localhost flask-with-runtime-env]# python -V
Python 2.7.18 :: Anaconda, Inc.

将解压后的2.7文件夹重新打包成2.7.tar.bz2,用于我们flask程序的运行环境

tar -zcvf 2.7.tar.bz2 2.7/

移动到我们项目的env目录下

mv 2.7.tar.bz2 resources/env/

3.4 打包项目并测试

将运行环境放到env下之后,我们可以直接执行build.sh进行打包。

sh build.sh

image-20200810202319962

执行完成后,查看target目录:

[root@localhost flask-with-runtime-env]# ls target/
flask-with-runtime-1.0.0.tar.gz

这个压缩包就是我们最终打包的程序,它里面带有独立的运行环境。只需要将它复制到要部署的机器上,解压,然后执行install脚本即可。

将压缩包复制到/opt/目录下

cp target/flask-with-runtime-1.0.0.tar.gz /opt/

去/opt目录下解压

[root@localhost flask-with-runtime-env]# cd /opt/
[root@localhost opt]# tar -zxvf flask-with-runtime-1.0.0.tar.gz 
flask-with-runtime-1.0.0/
flask-with-runtime-1.0.0/application/
flask-with-runtime-1.0.0/application/main.pyc
flask-with-runtime-1.0.0/bin/
flask-with-runtime-1.0.0/bin/start
flask-with-runtime-1.0.0/bin/stop
flask-with-runtime-1.0.0/env/
flask-with-runtime-1.0.0/env/2.7.tar.bz2
flask-with-runtime-1.0.0/scripts/
flask-with-runtime-1.0.0/scripts/flask.service.template
flask-with-runtime-1.0.0/scripts/install.sh

进入flask-with-runtime-1.0.0目录,执行安装脚本

cd flask-with-runtime-1.0.0
[root@localhost flask-with-runtime-1.0.0]# sh scripts/install.sh 
Created symlink from /etc/systemd/system/multi-user.target.wants/flask-application.service to /usr/lib/systemd/system/flask-application.service.
Installed successfully.
Please run command 'systemctl status flask-application' for more information about service.

查看运行状态

systemctl status flask-application

image-20200810203352606

访问目标主机:5000

0%