Wait the light to fall

第二十二天 - 使用 Carton 进行 Mojolicious 应用程序部署

焉知非鱼

你有一个可爱的Mojolicious应用程序,它是时候部署它了!

但是……它不能在生产服务器上运行!到底是怎么回事?哦,不,您所依赖的模块与开发服务器上的版本不同。你能做什么?

实际上,一些模块发展得很快(Hello Mojolicious!),这没有毛病,但可能会导致不兼容的变化。

还有一些可以在版本中解决或引入的错误,如果您的版本错误,则会遇到这些错误。

Cpanfile来救援 #

Cpanfile是一种用于描述Perl应用程序的CPAN依赖关系的格式。

有了cpanfile,我们可以列出我们需要的模块,但我们也可以强制模块的最小版本,它们的最大版本……或者说“我想要那个模块的确切版本”。

但我们也可以列出可选模块:您可以支持不同的数据库,但如果用户想要使用PostgreSQL,则不必安装与MySQL相关的模块。

这是一个例子cpanfile

# Do not ask for a specific version
requires 'DateTime';
# Ask a specific version
requires 'Plack', '== 1.0';
# Ask a minimal version
requires 'Net::DNS', '>= 1.12';
# Or
requires 'Net::DNS', '1.12';
# Ask a maximal version
requires 'Locale::Maketext', '< 1.28';
# Give a range
requires 'Mojolicious', '>= 7.0, < 8.0';

# Optional modules
feature 'postgresql', 'PostgreSQL support' => sub {
    requires 'Mojo::Pg';
};
feature 'mysql', 'MySQL support' => sub {
    requires 'Mojo::mysql';
};
feature 'ldap', 'LDAP authentication support' => sub {
    requires 'Net::LDAP';
};

Cpanfile格式可以做更多(推荐模块,用于特定阶段(需求configuretest…),使用没有公布关于CPAN …模块),但是这是一个关于 Carton 的文章:我让你读cpanfile文档🙂

留意:小心在 README 文件中列出非Perl的依赖关系1,像 Mojo::Pg 中的 libpq-dev😉

Cpanfile可以由cpanminusCarton使用

转到包含 cpanfile 的目录并执行:

cpanm --installdeps .

Etvoilà!

请注意,features尚未安装模块。你可以安装它们:

cpanm --installdeps . --with-feature postgresql

或者,安装所有features模块,但不安装mysql

cpanm --installdeps . --with-all-features --without-feature mysql

所以,现在,我们可以确定我们的应用程序依赖于系统的良好版本。

但是,如果我们在该系统上托管其他具有冲突要求的应用程序呢?

Cpanm 能够在特定的文件夹中安装模块(谢谢你,local::lib),但是在我们的应用程序目录中安装我们的依赖项是不是很方便?我们总是知道我们的依赖关系在哪里。

Carton来了 #

Carton是Perl模块依赖管理器。想想 Ruby 中的 bundler。 想想 Node.js 中的 npm

npm,Carton 在应用程序的目录中安装依赖关系。

部署 #

首先,安装 Carton:

cpanm Carton

然后,我们可以安装我们的依赖项:

carton install

我们的依赖项将安装在一个名为的目录中local。但还有更多:Carton将生成一个cpanfile.snapshot文件,其中包含我们的依赖项的确切版本,允许我们强制执行那些确切的版本(随应用程序一起提供)。

在我们的cpanfile示例中,我们要求Mojolicious版本大于或等于7.0且小于8.0。在我们的开发服务器上的安装和生产服务器上的安装之间,我们依赖的一些较新版本的模块可能已经发布。假设在我们的开发环境中我们有7.77 Mojolicious和7.90并且有些东西已经改变,这会导致问题(例如,来自Mojolicious :: Plugin :: DefaultHelpers的延迟助手已经在7.78中弃用并且在7.90中被移除)。

7.77和7.90版本都在我们的产品系列中,但我们的应用程序无法在生产服务器上运行…我们需要使生产环境尽可能与开发环境相同。

为此,由于我们cpanfile.snapshot的开发服务器有一个文件,我们可以这样做:

carton install --deployment

这将安装快照中列出的模块的确切版本。

特征 #

默认情况下,carton install将安装所有功能依赖项,但我们可以停用一些:

carton install --deployment --without-feature mysql

为了为所有模块(甚至是可选模块)提供正确的版本,请carton install在开发服务器上执行,并--without-feature仅在部署应用程序时使用:您需要cpanfile.snapshot包含所有模块。

开始申请 #

为了能够使用local包含依赖项的目录,可以为命令添加前缀carton exec。因此,要使用内置服务器hypnotoad启动Mojolicious应用程序,请执行以下操作:

carton exec -- hypnotoad script/my_application

这适用于您可以对您的应用程序执行的所有操作。例:

carton exec -- script/my_application routes

请注意两个破折号:它们避免使用纸盒来解释传递给脚本的参数。这将显示您的应用程序的帮助消息:

carton exec -- script/my_application --help

这将显示纸箱的帮助信息:

carton exec script/my_application --help

看到不同?😉

捆绑依赖项 #

为了更快地安装,carton可以将依赖项的所有tarball捆绑到一个目录中,这样您甚至可以安装CPAN上不可用的依赖项,例如内部分发,即DarkPAN:

carton bundle

这将捆绑tarball vendor/cache。您现在可以使用以下命令安装依赖项:

carton install --cached

结合--deployment选项,您可以避免查询CPAN Meta DB等数据库或从CPAN镜像下载文件。

您甚至可以避免在生产服务器上安装Carton的需要(但是您需要添加local目录@INC以启动您的应用程序,因为您无法使用carton exec):

cpanm -L local --from "$PWD/vendor/cache" --installdeps --notest --quiet .

结论 #

Carton和cpanfile是缓解Mojolicious应用程序部署的好方法。它不仅可以避免在README或INSTALL文件中列出应用程序所需的所有依赖项,而且可以加速部署并使它们更安全,因为它确实可以降低由于依赖项版本不良而导致的错误风险。