我们在Linux上运行了几个Python 2.6应用程序。其中一些是Pylons Web应用程序,其他只是我们使用nohup
从命令行运行的长时间运行的进程。我们还在开发和生产中使用virtualenv
。 将这些应用程序部署到生产服务器的最佳方法是什么?
在开发中,我们只需将源代码树放入任何目录,设置virtualenv并运行 - 足够简单。我们可以在生产中做同样的事情,也许这是最实用的解决方案,但在生产中运行svn update
感觉有点不对劲。我们也试过fab
,但它从来没有第一次运作。对于每个应用程序,出现其他问题。令我感到震惊的是整个过程太难了,因为我们想要实现的目标从根本上说非常简单。这是我们对部署过程的期望。
真的是这样!这有多难?
答案 0 :(得分:23)
setuptools结合virtualenv和pip,可以更轻松地开发和部署Python代码。
我发现,最棘手的部分是运行一个开发环境,尽可能地反映部署的设置,同时尊重Pythonic工具和习语。但事实证明,使用pip和setuptools可以很容易地实现这一点,它们允许您在不移动文件的情况下将开发树“安装”到Python环境中。 (实际上setuptools会自行完成这一切,但是pip更好地充当前端句柄依赖项。)
另一个关键问题是在两个环境中准备一个包含已知包的干净环境。 Python的virtualenv在这方面是一个神派,允许您使用自己选择的包配置完全自定义的Python环境,无需root访问权限或OS包(rpm或dpkg),并且不受任何包和版本的限制恰好安装在你的发行版上。
最后,一个令人讨厌的bug-bear是难以创建与PYTHON_PATH搭配良好的命令行脚本。 setuptools也非常优雅地处理了这个问题。
(为了简单起见,这是相当规范的。请随意分开。)
从工作目录中,设置一个新的Python虚拟环境:
$ python <untarred_directory>/virtualenv.py venv
您希望在此虚拟环境中完成大部分工作。使用此命令执行此操作(.
是source
)的快捷方式:
$ . venv/bin/activate
安装pip:
$ easy_install pip
为您要创建的每个可安装程序包创建目录。
一旦树状结构准备就绪,您几乎已准备好开始编码。但是现在,依赖于彼此的软件包在部署环境中无法看到彼此。这个问题通过setuptools提供的一个巧妙的小技巧解决,以及哪个pip使用。对于您正在开发的每个包,请运行以下命令(确保您位于项目的虚拟环境中,如上面的步骤3所示):
$ pip install -e pkg1
此命令会将pkg1
安装到您的虚拟环境中,并且不会复制任何文件。它只是添加指向包的开发根目录的site-packages
目录的链接,并在该根目录中创建一个egg-info目录。您也可以在没有点的情况下执行此操作,如下所示:
$ cd pkg1
$ python setup.py develop
它通常会起作用,但如果您有第三方依赖项(应该在setup.py中列出,如setuptools文档中的here所述),那么pip会更聪明地找到它们。
需要注意的一点是,setuptools和pip都没有任何关于在你自己的包中找到依赖关系的聪明之处。如果目录B中的PkgB依赖于目录A中的PkgA,则pip install -e B
将失败,因为pip无法知道在目录A中可以找到PkgA;它将尝试并失败,从其在线存储库源下载PkgA。解决方法只是在每个包依赖后安装它们。
此时,您可以启动python,加载其中一个模块并开始使用它。您可以编辑代码,下次导入时它将立即可用。
最后,如果要使用包创建命令行工具。不要手工写。你最终会得到一堆可怕的PYTHON_PATH黑客,这些黑客从来都不能正常工作。只需阅读setuptools文档中的automatic script creation即可。这样可以免除你的痛苦。
当您的软件包准备好执行操作时,您可以使用setup.py来创建部署软件包。这里有太多的选择,但以下内容应该让你开始:
$ cd pkg1
$ python setup.py --help
$ python setup.py --help-commands
由于问题的广泛性,这个答案必然是不完整的。我没有处理长期运行的服务器,Web框架或实际部署过程本身(特别是使用pip install的--index-url
来管理第三方和内部包的私有存储库以及-e vcs+...
,这将从svn,git,hg或bzr中提取包。但我希望我已经给你足够的绳索将它们捆绑在一起(只是不要把它自己挂起来: - )。
答案 1 :(得分:6)
这真的不难。您需要主要使用buildout和supervisord IMO。
虽然学习构建可能需要一点时间,但它值得,因为在重复设置中它会减少疼痛。
关于nohup: nohup方法不适合严肃的部署。我对supervisord有很好的经验。它是运行生产python应用程序的绝佳解决方案。这很容易设置。
以下一些具体答案。
答案 2 :(得分:5)
我一直致力于为我们的工作项目实施这项工作。这涉及到一些不同的部分。
首先,我们使用他们的引导功能自定义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应用程序。
您可以使用Google代码搜索浏览大量优质的结构文件。我知道我为自己的使用而欺骗了一些。
这绝对是复杂的,有几个部分,以使事情顺利进行。一旦你开始运行,事情的灵活性和速度就会很棒。
答案 3 :(得分:2)
请查看Buildout以获得可重现的部署。
答案 4 :(得分:0)
另一项面料投票(尚未尝试过Buildout)。我们已成功使用它几个月了。
如果您遇到布料问题,另一个选项是Capistrano。效果很好(即使对于非rails应用程序)。只停止使用它因为使用Ruby来部署Python应用程序感觉很奇怪;)
答案 5 :(得分:0)
我会使用rsync从您的生产“主要”服务器向外同步,从您的“beta测试”平台向您的生产“主要”服务器同步。
rsync的好处是只复制那些已更改的文件,并仅复制部分更改的文件,并在所有计算机上验证最终的完整性和相同内容。可以在以后轻松地继续进行部分通过和中断的更新,从而使您的部署更加强大。
Subversion或Mercurial在这种情况下也不是一个坏主意。 Mercurial有 允许您“拉”或“推”而不是仅从一个中央源更新的优点。您可能会发现一些有趣的案例,其中分散模型(mercurial)效果更好。
答案 6 :(得分:0)
如果你是一个扩建人,那么你应该知道minitage.recipe.scripts能够生成一个文件来设置你的python环境。来自您的Web服务器的源和您的buildout是完全可移植的。
答案 7 :(得分:0)
听起来你想要的是构建脚本。所以写一个,使用shell,python,ant或你最喜欢的构建工具。如果您不喜欢用XML编写,pant允许您在python中编写ant脚本。有几个人提到了buildout,但我对此没有任何经验。
首先定义您的步骤。听起来你想:
如果您正在进行负载平衡或依赖于其他服务生产,您可能想要找出一种方法来推出有限的范围,这样您的所有客户都不会立即受到影响。如果你有一个类似生产的登台环境,也可能满足这种需求。