使用Composer的开发/生产交换机时如何正确部署?


178

Composer可以选择仅在开发过程中加载多个依赖项,因此这些工具将不会安装在生产环境中(在实时服务器上)。从理论上讲,这对于仅在开发中有意义的脚本非常方便,例如测试,伪数据工具,调试器等。

可行的方法是require-dev使用开发中所需的工具添加一个附加块:

"require-dev": {
    "codeception/codeception": "1.6.0.3"
}

然后(理论上)通过

composer install --dev

问题与疑问:

Composer改变了行为,installupdate在2013年发生了巨大变化,require-dev-dependencies现在已默认安装(!),可以随意创建一个带require-dev块的composer.json 并执行一个composer install重现。

作为最流行的部署方式,是推动作曲家。锁定(保存您当前的作曲家设置),然后composer install在生产服务器上执行,这也会安装开发资料。

安装-dev依赖项的情况下进行部署的正确方法是什么?

注意:我正在尝试在此处创建规范的Q / A,以阐明怪异的Composer部署。随时编辑此问题。


@All:不知道是哪里的赏金是:(我会开始另一种方法。
SLIQ

1
如果您没有积极地奖励它,并且没有答案被接受或获得足够的投票,那么没人会得到赏金。
Sven 2014年

2
我个人根本不喜欢这种方法。本composer.lock不应该被添加到Git的回购,从来没有。正确的方法是在登台上使用composer update,然后将文件同步到生产环境中(当然,如果一切正常)。暂存必须是生产环境的精确副本。composer.lock应该是的一部分.gitignore
名词

6
composer.lock已明确包含在您的CSV中!!!您还如何确保每个人都使用相同的版本?因此,切勿从您的CSV中排除composer.lock!
Tobias Gaertner

3
@TobiasGaertner我认为您的意思是VCS(版本控制软件),但否则,您是正确的,并且符合项目的官方建议
熊加米奥夫

Answers:


325

为什么

恕我直言,有充分的理由说明为什么Composer将--dev默认使用该标志(在安装更新时)。Composer通常在所需行为的方案中运行:

基本的Composer工作流程如下:

  • 开始一个新项目:composer.phar install --dev,json和锁定文件已提交到VCS。
  • 其他开发人员开始从事该项目:VCS和的签出composer.phar install --dev
  • 开发人员添加依赖项:composer.phar require <package>,添加--dev如果要在require-dev部分中提交包(并提交)。
  • 其他人也可以:(结帐和) composer.phar install --dev
  • 开发人员需要较新版本的依赖项: composer.phar update --dev <package>和提交)。
  • 其他人也可以:(结帐和) composer.phar install --dev
  • 项目已部署: composer.phar install --no-dev

如您所见 --dev标志的使用(远)次数比--no-dev尤其是,尤其是当从事该项目的开发人员数量增加时。

生产部署

在不安装“ dev”依赖项的情况下进行部署的正确方法是什么?

好,composer.jsonand composer.lock文件应该提交给VCS。不要忽略composer.lock它,因为它包含有关应使用的程序包版本的重要信息。

执行生产部署时,可以将--no-dev标志传递给Composer:

composer.phar install --no-dev

composer.lock文件可能包含有关dev软件包的信息。没关系 该--no-dev标志将确保未安装这些dev软件包。

当我说“生产部署”时,是指旨在用于生产中的部署。我不是在争论一个composer.phar install应该在生产服务器上或可以在此进行审查的登台服务器上完成。那不是这个答案的范围。我只是指出如何composer.phar install不安装“ dev”依赖项的情况下进行操作。

题外话

--optimize-autoloader标志在生产中也可能是理想的(它会生成一个类映射,这将加速应用程序中的自动加载):

composer.phar install --no-dev --optimize-autoloader

或在完成自动部署后:

composer.phar install --no-ansi --no-dev --no-interaction --no-plugins --no-progress --no-scripts --no-suggest --optimize-autoloader

如果你的代码库支持的话,你可以换出--optimize-autoloader--classmap-authoritative。更多信息在这里


5
我同意大部分的说法,只有一个例外。“ composer install --no-dev”应仅在登台环境中执行,并且该环境应被视为不可变的。我不想直接在我的生产服务器上下载任何依赖项,而无需进行预览/过渡。这只是额外的警告。
可缩放

3
@Scalable:尽管我同意你的观点(Sven在他的回答中很好地涵盖了这一点),但这不是我的回答的范围,也不是我所说的“生产部署”。我添加了一个段落以使其清楚。
贾斯珀(Jasper N. Brouwer)2015年

5
实际上,我认为默认值应该是不太危险的选择。将--dev设置为默认值,并在生产环境中意外安装作曲家可能是致命的。
赫克托·奥多涅斯

3
好点的--optimize-autoloader。还请考虑--classmap-authoritative-从此处的文档getcomposer.org/doc/03-cli.md中,您可以看到:“仅从类映射自动加载类。隐式启用--optimize-autoloader”,因此,如果您知道类“是那里”,除非您动态生成类,否则这可能应该在您的产品环境中发生。
哈维·蒙特罗

6
好的答案,我建议optimize-autoloader直接在以下位置添加composer.json{"config": { "optimize-autoloader": true } }
Yvan

79

实际上,我强烈建议AGAINST在生产服务器上安装依赖项。

我的建议是在部署机器上签出代码,根据需要安装依赖项(如果代码投入生产,则不包括安装开发依赖项),然后将所有文件移至目标计算机。

为什么?

  • 在共享主机上,您可能无法进入命令行
  • 即使您这样做,PHP可能仍在命令,内存或网络访问方面受到限制
  • 可能未安装存储库CLI工具(Git,Svn),如果您的锁定文件记录了签出某个提交而不是以ZIP形式下载该提交(您使用--prefer-source或Composer已将其提交)的依赖项,则失败没有其他方法可以获取该版本)
  • 如果您的生产机器更像是一台小型测试服务器(例如Amazon EC2微型实例),则可能甚至没有安装足够的内存来执行 composer install
  • 虽然composer尝试不间断运行,但您对以部分中断的生产网站结尾感到如何,因为在Composers安装阶段无法加载某些随机依赖项

长话短说:在您可以控制的环境中使用Composer。您的开发机器确实合格,因为您已经拥有操作Composer所需的所有东西。

在不安装-dev依赖项的情况下进行部署的正确方法是什么?

使用的命令是

composer install --no-dev

这将在任何环境中都有效,无论是生产服务器本身,还是部署机器,或者是应该进行最后检查以发现是否有任何开发需求未正确用于实际软件的开发机器。

该命令将不会安装或主动卸载composer.lock文件中声明的开发要求。

如果您不介意在生产服务器上部署开发软件组件,则运行composer install将完成相同的工作,但只是增加了移动的字节数,并创建了更大的自动加载器声明。


14
有趣的工作流程,但有一个很大的缺点:信息库绝不应该包含供应商文件夹/内容本身(在Composer页面上的官方声明),因此决不能在基于git的部署中将它们直接推入生产环境(这是常见的标准afaik,如我错了请纠正我)。因此,基本上上述解决方案仅适用于“老式” FTP部署!请让我们进一步讨论...
Sliq 2014年

17
我建议的工作流程不包括通过GIT将代码推送到生产服务器。实际上,我建议不要这样做,因为这样做会迫使您在生产服务器上安装Composer依赖项,这可能会带来许多问题。如果要使部署顺利进行,则必须先组装运行该应用程序所需的所有代码,然后再销毁当前版本并进行替换。不喜欢FTP?通过SSH进行RSync,然后通过翻转符号链接来切换版本。但是,如果您愿意,也可以在产品中推送,签出和Composer安装。
Sven 2014年

2
@Panique:我刚刚看到了您的部分评论,我必须回答:“在基于git的部署中推送到生产环境(这是常见的标准afaik,如果我错了,请纠正我)”-不,这不是通用标准。这只是做到这一点的一种方法。
Sven 2014年

1
我所在的团队已将其成功地整合到他们的工作流程中。我们有一台构建机器(当然是詹金斯):1)从SC中签出2)运行composer安装/更新3)运行单元测试4)删除开发依赖项5)生成phar文件(app-1.34.phar等)。有一个单独的机制可以通知,并决定何时获取该文件,将其传输到何处以及如何处理。一些团队选择将phar放在服务器上后再打开包装,而另一些团队则按原样运行它。它为我们的部署的稳定性和可重复性提供了很大的信心。
乔什·约翰逊

3
我同意这个答案100%。Composer不应安装在部署服务器上,也不应该安装在git上。连续部署/集成服务器完全应该管理源和依赖项的获取:git pull> composer install> deploy
Eric MORAND

4

现在require-dev默认情况下启用了Now ,对于本地开发,您可以执行composer installcomposer update无需--dev选择。

要部署到生产环境时,需要确保composer.lock没有来自的任何软件包require-dev

你可以用

composer update --no-dev

在本地进行测试后,--no-dev您可以将所有内容部署到生产环境并根据进行安装composer.lock。您在--no-dev这里再次需要该选项,否则作曲家将说“锁定文件不包含require-dev信息”

composer install --no-dev

注意:小心任何可能在开发和生产之间造成差异的事物!我通常尝试尽可能地避免require-dev,因为包括dev工具并不是很大的开销。


1
实际上,这在细节上是不正确的。无需检查composer.lock开发依赖项。您只需运行composer install --no-dev,就只会安装常规依赖项-实际上,Composer还将在此步骤中删除所有dev依赖项。
Sven 2014年

如果我的本地计算机composer.lock具有开发依赖关系(并可能影响非开发软件包的版本),那么我想对其进行更新以反映其在生产环境中的状况。这也会迫使您composer install --no-dev在生产中运行,这composer install会出错。从技术上讲,我认为您是对的;这不是必需的,但这是我喜欢的额外安全等级。
dave1010 2014年

好的演示场景:您的应用需要dev/toolprod/lib:~1.0。最新的prod / lib是1.3,但dev / tool也需要prod/lib:1.1.*。结果:您将安装版本1.1.9(1.1.x分支的最新版本)并在开发期间使用它。我会说仅进行更新并不安全--no-dev,因此包括最新的prod / lib 1.3并假设一切无需测试即可正常工作。也许由于缺乏开发人员/工具,所以测试是不可能的。我认为,因为在生产中不需要dev / tool,所以不应将其推出,但那时该软件必须使用prod / lib 1.1.9。
Sven 2014年

如果您正在使用,--no-dev则需要在本地进行测试,就像我在答案中提到的那样。我仍然建议不要使用--no-dev
dave1010 2014年

因此,基本上,您建议这样composer update做:然后进行一些开发,然后进行composer update --no-dev,然后进行发布测试,然后进行生产并进行composer install --no-dev。两个问题:1.我无法在没有开发依赖的情况下测试发行版,并且2.无法在生产环境中使用例如Git进行安装。
Sven 2014年

3

在生产服务器上,我重命名vendorvendor-<datetime>,并且在部署期间将有两个供应商目录。

HTTP cookie使我的系统选择新的供应商 autoload.php,并且在测试之后,我在它们之间进行了完全原子/即时切换,以禁用所有将来请求的旧供应商目录,然后几天后删除了先前的目录。

这样可以避免由我在apache / php中使用的文件系统缓存引起的任何问题,并且还允许任何活动的PHP代码继续使用以前的供应商目录。


尽管有其他答案建议反对,但我还是亲自跑步 composer install在服务器上,因为它比暂存区域(笔记本电脑上的VM)中的rsync快。

我用--no-dev --no-scripts --optimize-autoloader。您应该阅读每个文档,以检查这是否适合您的环境。


2

我认为最好将流程自动化:

在您的git仓库中添加composer.lock文件,确保在发布时使用composer.phar install --no-dev,但是在您的dev机器中,您可以使用任何composer命令而无需担心,这将不会投入生产,生产将其依赖项基于锁定文件。

在服务器上,您签出该特定版本或标签,并在替换应用程序之前运行所有测试,如果通过测试,则可以继续进行部署。

如果测试依赖于dev依赖项,因为composer没有测试范围的依赖关系,则可以使用dev依赖项(composer.phar install)运行测试,这不是一个非常好的解决方案,删除供应商库,运行composer.phar install- -无开发,它将使用缓存的依赖项,因此速度更快。但是,如果您知道其他构建工具中范围的概念,那将是一个hack。

自动化它,忘记其余的,去喝啤酒:-)

PS .:和@Sven注释一样,不要检出composer.lock文件不是一个好主意,因为这会使composer安装作为composer更新工作。

您可以使用http://deployer.org/实现自动化,这是一个简单的工具。


2
不提交和退房composer.lock将导致composer install行为像composer update。因此,您部署的版本不是您开发的版本。这很可能会带来麻烦(并且鉴于Composer中唯一最近解决的带有“替换”的安全性问题,这一点尤其如此)。您切勿在composer update无人看管的情况下运行它,以确保它不会破坏任何内容。
Sven 2014年

1
@Sven这是在同一注释中建议在部署之前自动运行单元测试的方式。但是您是对的,最好还是保留composer.lock文件。
Giovanni Silva

现在,您只需解释一下:如何在没有像PHPUnit这样的dev依赖项的服务器上运行测试?
Sven 2014年

如果将依赖项,测试和部署放到一个工具中,例如Java Gradle或SBT甚至Maven(maven不太好),那就太好了。一种使作曲家phpunit和部署协同工作的PHP工具。甚至是Gradle或Scala SBT插件都可以做这些事情,因为它们是不可知的构建工具,所以该插件甚至可以与最小化javascript,编译sass,最小化css等资产一起使用。有人知道吗?
Giovanni Silva

1
当然,这是在服务器中完成的,以测试实际环境,但不能直接在站点虚拟主机中进行,您可以在单独的临时文件夹中进行此操作,并将成功后的结果移至虚拟主机中
Giovanni Silva 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.