第二十二天 - 使用 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格式可以做更多(推荐模块,用于特定阶段(需求configure
,test
…),使用没有公布关于CPAN …模块),但是这是一个关于 Carton 的文章:我让你读cpanfile文档🙂
留意:小心在 README 文件中列出非Perl的依赖关系1,像 Mojo::Pg
中的 libpq-dev
😉
Cpanfile可以由cpanminus或Carton使用。
转到包含 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文件中列出应用程序所需的所有依赖项,而且可以加速部署并使它们更安全,因为它确实可以降低由于依赖项版本不良而导致的错误风险。