我们在Linux上运行了几个Python 2.6应用程序.其中一些是Pylons Web应用程序,其他只是我们从命令行使用的长时间运行的进程nohup
.我们也在virtualenv
开发和生产中使用.将这些应用程序部署到生产服务器的最佳方法是什么?
在开发中,我们只需将源代码树放入任何目录,设置virtualenv并运行 - 足够简单.我们可以在生产中做同样的事情,也许这确实是最实用的解决方案,但svn update
在生产中运行感觉有点不对劲.我们也试过fab
,但它从来没有第一次工作.对于每个应用程序,出现其他问题.令我感到震惊的是,整个过程太过艰难,因为我们想要实现的目标从根本上说非常简单.这是我们从部署过程中想要的.
我们应该能够运行一个简单的命令来部署应用程序的更新版本.(如果初始部署涉及一些额外的复杂性,那很好.)
当我们运行此命令时,它应该将某些文件从Subversion存储库或本地工作副本中复制到服务器上的指定"环境",这可能意味着不同的virtualenv.我们在同一台服务器上有应用程序的暂存和生产版本,因此它们需要以某种方式保持独立.如果它安装到站点包中,那也没关系,只要它有效.
我们在服务器上有一些应该保留的配置文件(即,不会被部署过程覆盖或删除).
其中一些应用程序从其他应用程序导入模块,因此它们需要能够以某种方式作为包引用彼此.这是我们最麻烦的部分!只要它在开发和生产中都可靠地运行,我不关心它是通过相对导入,站点包还是其他方式工作.
理想情况下,部署过程应自动安装我们的应用程序所依赖的外部包(例如psycopg2).
真的是这样的!它能有多难?
通过setuptools与virtualenv和pip的结合,Python代码的开发和部署变得更加容易.
我发现,最棘手的部分是运行一个开发环境,尽可能地反映部署的设置,同时尊重Pythonic工具和习语.但事实证明,使用pip和setuptools可以很容易地实现这一点,它们允许您在不移动文件的情况下将开发树"安装"到Python环境中.(实际上setuptools会自行完成这一切,但是pip更好地充当前端句柄依赖项.)
另一个关键问题是在两个环境中准备一个包含已知包的干净环境.Python的virtualenv在这方面是一个神派,允许您使用自己选择的包配置完全自定义的Python环境,无需root访问权限或OS包(rpm或dpkg),并且不受任何包和版本的限制恰好安装在你的发行版上的.
最后,一个令人烦恼的bug-bear是难以创建与PYTHON_PATH一起使用的命令行脚本.setuptools也非常优雅地处理了这个问题.
(为了简单起见,这是相当规范的.请在适当的时候随意分歧.)
准备一个Python东西可以称之为家的工作目录.
从本页底部获取最新的virtualenv 并解压缩(无所谓).
从工作目录中,设置一个新的Python虚拟环境:
$ python/virtualenv.py venv
您将希望在此虚拟环境中完成大部分工作.使用此命令执行此操作(.
是一个快捷方式source
):
$ . venv/bin/activate
安装点子:
$ easy_install pip
为要创建的每个可安装程序包创建目录.
在每个目录中,您将需要一个setup.py来定义包的内容和结构.setuptools 文档是一个非常好的资源,可以开始使用它.值得花些时间吸收它的大块.
树形结构准备就绪后,您几乎已准备好开始编码.但是现在,依赖于彼此的软件包在部署环境中无法看到彼此.这个问题通过setuptools提供的一个巧妙的小技巧解决,以及哪个pip使用.对于您正在开发的每个包,请运行以下命令(确保您位于项目的虚拟环境中,如上面的步骤3所示):
$ pip install -e pkg1
此命令将安装pkg1
到您的虚拟环境中,并且不会复制任何文件.它只是添加一个site-packages
指向包的开发根目录的链接,并在该根目录中创建一个egg-info目录.您也可以不用pip执行此操作,如下所示:
$ cd pkg1 $ python setup.py develop
它通常会工作,但如果你有第三方依赖(这应该在setup.py上市,作为解释这里的setuptools的文档中),PIP就是找到他们更聪明.
需要注意的一点是,setuptools和pip都没有任何关于在你自己的包中找到依赖关系的聪明之处.如果目录B中的PkgB依赖于目录A中的PkgA,pip install -e B
则会失败,因为pip无法知道在目录A中可以找到PkgA; 它将尝试并失败,从其在线存储库源下载PkgA.解决方法是在依赖项之后安装每个包.
此时,您可以启动python,加载其中一个模块并开始使用它.您可以编辑代码,下次导入时它将立即可用.
最后,如果要使用包创建命令行工具.不要手工写.你最终会得到一堆可怕的PYTHON_PATH黑客,这些黑客从来都不能正常工作.只需阅读setuptools文档中的自动脚本创建.这将为你带来很多悲伤.
当您的程序包准备好执行操作时,可以使用setup.py来创建部署程序包.这里有太多的选择,但以下内容应该让你开始:
$ cd pkg1 $ python setup.py --help $ python setup.py --help-commands
由于问题的广泛性,这个答案必然是不完整的.我没有处理长期运行的服务器,Web框架或实际的部署过程本身(特别是使用pip install --index-url
来管理第三方和内部软件包的私有存储库-e vcs+...
,这将从svn中提取软件包,git ,hg或bzr).但我希望我已经给你足够的绳索将它们捆绑在一起(只是不要把它自己挂起来:-).
这真的不难.你需要主要玩buildout和supervisord IMO.
虽然学习扩建可能需要一点时间,但它值得,因为在重复设置中它会减少痛苦.
关于nohup: nohup方法不适合严肃的部署.我对supervisord有很好的经验.它是运行生产python应用程序的绝佳解决方案.它很容易设置.
以下是一些具体答案.
单个命令部署:Buildout就是答案.我们使用它几年以来没有太多问题
通常就像你查看来源一样.然后运行buildout.此外,将安装程序复制到站点包中可能不是一个好主意.更好地保持环境分离.
配置不会被覆盖.
您可以/应该考虑为普通包装建立鸡蛋.就像你可以为包构建egg(比如commonlib)并将其上传到你的代码库中一样.然后,您可以在buildout.cfg中将其指定为依赖项
Buildout能够构建与中央/顶级安装完全分离的大多数基本软件包.但是根据我的经验,如果作为操作系统包安装了带有c扩展名的python包,那就容易多了.
我一直在努力为我们的工作项目实施这个.这涉及到一些不同的部分.
首先,我们使用他们的引导功能自定义virtualenv.py,以添加您自己的自定义创建后功能和标志.这些允许我们定义常见的项目类型,并为我们提供单个命令来创建新的virtualenv,从git存储库检出项目,并使用pip和requirements.txt文件将任何需求安装到virtualenv中.
所以我们的命令看起来像:python venv.py --no-site-packages -g $ git_proj -t $ tag_num $ venv_dir
http://pypi.python.org/pypi/virtualenv http://pip.openplans.org/
现在,它让我们完成了对现有项目的初步检查.在我们工作和更新项目时,我们在每个项目中使用fabric命令来构建版本,然后部署它们:
http://docs.fabfile.org/0.9.0/
我有一个fab命令:make_tag检查未使用的提交,打开需要更新版本字符串的文件,构建和上传sphinx文档,然后将最终标记提交到存储库.
另一方面是fab deploy命令,它将通过ssh执行指定标记的git co,对任何新需求运行pip更新,运行所需的任何数据库迁移,然后重置Web服务器(如果这是Web应用程序) .
以下是标记功能的示例:http://www.google.com/codesearch/p?hl = en#9tLIXCbI4vU/fabfile.py&q = frafile.py%20git%20tag_new_version&sa = N&cd = 1&ct = rc&l = 143
您可以使用Google代码搜索浏览大量优质的结构文件.我知道我为自己的使用而欺骗了一些.
这绝对是复杂的,有几个部分,以使运行顺利.一旦你开始运行,事情的灵活性和速度就会很棒.