我倾向于使用Git将生产代码部署到Web服务器。这通常意味着主Git存储库托管在可以通过ssh访问的某个位置,生产服务器为该克隆的存储库提供服务,同时限制对.git/.gitignore的访问。当我需要更新它时,我只需从主存储库中拉到服务器的存储库即可。这有几个优点:


如果有任何问题,回滚到较早的版本非常容易-只需将其签出即可。文件被修改,检查起来就像git status一样容易,并且如果服务器的存储库已被修改,那么下次我尝试拉时就会很明显。
这意味着在源代码中还有一个副本万一发生坏事。
更新和回滚既简单又快速。

这可能会有一些问题:原因是Web服务器决定应为.git/目录提供服务,所有以前的源代码都可以被所有人读取。从历史上看,有些(大)公司犯了这个错误。我正在使用.htaccess文件来限制访问,所以我认为目前没有任何危险。也许是一项整合测试,以确保没有人能按顺序读取.git/文件夹?但这并不比访问当前版本更糟。毕竟,这些修订在定义上是过时的。

所有这些,我相信使用Git将代码部署到生产中是相当安全的,并且比rsyncftp或复制它要容易得多。过度。你觉得呢?

评论

标准做法不是将git存储库从htdoc文件夹上移到一个级别,这样就不会发生意外提供它的情况?
这是一个很好的建议,我正在为最新的个人项目这样做。但是在另一个项目中,我的客户存储库的组织方式不同(htdoc位于存储库的根目录),因此该问题仍然适用。

到目前为止,我还没有机会与专门的测试服务器和质量检查团队一起工作(可能很差)。我在开发机上进行了全面测试,仅在特定的迭代中部署新功能。然后,如果需要在下一次迭代之前进行错误修复,请在单独的分支上进行。例如,发布了0.6版,并从0.7开始了工作。在0.6上发现了bug,在分支0.6中应用了修复程序,并将其合并到master分支中。生产然后拉分支0.6。直到发布0.7,所有修补程序都首先进入分支0.6。有时(并非总是如此),我会为生产版本提前创建一个单独的分支

这真的是一个安全问题吗?

您始终可以使用诸如Gradle,Maven,Etc之类的Package Manager套件将文件部署到HTDOCS文件夹,以便您专门忽略./git等。在服务器上的单独文件夹中更新GIT,而不是运行PM进行部署到正确的位置。这就是它们存在的原因。

#1 楼

我会考虑使用git进行部署非常好的做法。

您列出的两个问题与使用git本身进行部署几乎没有关系。用.git/替换包含数据库密码的配置文件,您会遇到相同的问题。如果我对您的Web根拥有读取权限,则对其中的任何内容都具有读取权限。这是服务器强化问题,您必须与系统管理部门讨论。

git在安全性方面提供了一些非常吸引人的优点。我什至会配置一个post-receive挂钩,以便在对master进行一次提交时自动将其部署到生产中。我当然假设工作流程类似于git flow。
如果遇到安全问题,git可以非常轻松地将生产环境中部署的代码回滚到以前的版本。这有助于阻止访问关键任务安全漏洞,而您需要花费一定时间才能正确修复该漏洞。
您可以执行一个系统,在该系统中,开发人员必须对他们所做的提交进行签名。如果发现蓄意的安全漏洞,这可以帮助跟踪谁将什么部署到生产中。


评论


很好的答案,我真的很期待在生产服务器中使用git!但是,我不愿意按照您(以及我阅读的其他几本)的建议使用自动推送。自动推送可以在您不需要时更改生产服务器,并且您可能会意外使服务器脱机。也许我缺少了一些东西,并使事情变得复杂化了,但是我更偏向于将ssh'进入生产服务器,先执行git fetch origin master,然后再执行git diff master origin / master。只有这样我才做git merge origin / master --ff-only。您对此事有什么想法吗?

–pedromanoel
2014年6月11日下午13:07

@pedromanoel我赞同这种思想流派,在这种情况下,您要求掌握的所有内容都应已准备好进行生产,因此不必担心。您的建议也可以。

–user10211
14年6月17日,11:51

我们的master分支将部署部署到Dev Web服务器。我们有一个QA,Staging和Production分支,它们映射到各自的环境。当我们要发布到生产环境时,我们只需要将经过测试的代码合并到生产分支中即可。这对我们来说很好。我们为此使用KUDU。不知道还有哪些其他工具可用。

– RayLoveless
2015年6月19日在20:44



@TerryChia您能建议任何教程/工具来设置自动部署的接收后挂钩吗?我们使用Kudu,但我发现为非保证站点设置非常棘手(我们在Prem上拥有自己的IIS服务器)。

– RayLoveless
15年6月19日在21:02

#2 楼

从git repo进行部署没有任何问题,实际上,这是一种很常见的做法,而且正如您所说的,与通过ftp或rsync复制文件相比,出错的可能性要小得多。

鉴于您提供的信息,我要注意以下几点:生产应该从发布标签进行部署。使用git flow或类似的方法在代码部署和标记创建方面获得更多处理。因为标签在给定时间是对代码的不变引用,所以它比指向可以由错误提交更新的master分支更稳定。
对于提供.git目录,这应该不是大问题。只需将前缀为.git的任何内容重定向到.htaccess中的404。
您的git身份验证应基于ssh密钥,因此无需在服务器上存储任何回购密码。

#3 楼

我将不同意这里的民意。 Git用于版本控制,而不是用于部署/ CI。 /> ...这并不是说您不应该继续做自己在做的事情。请记住,随着您的职业发展,您正在从事的项目可能会超出纯粹基于git的部署工作流。

范式的主要转变是停止考虑部署分支机构,并开始考虑部署构建结果,并注入环境依赖项以使基础架构与分支策略脱钩。例如,使用上面关于“部署文件”和回滚的范例。如果要部署文件,则可以在生产服务器上保留该应用程序的多个版本,并且如果需要回滚,可以通过重新符号化Web根目录将Web服务器指向较旧的版本。两个shell命令,与使用git相比,停机时间为几微秒,错误空间更小。您已经准备好进行开发,但是其他一些无法进行质量检查的内容。因此,您需要执行一些丑陋的操作-从阶段中删除不良提交,重新部署阶段,还剥离或修复开发中的不良提交,并希望开发和登台不会最终不同步。

相反,如果您从主服务器上断开发布分支,将准备好进入发布分支的内容合并并生成结果,在AWS上启动测试服务器并将其部署到该服务器,然后执行质量检查和对临时登台服务器进行功能测试,然后将相同结果推送到生产集群并进行部署?然后停用您启动的临时登台框,将发行版合并到母版中,并用发行号标记母版。

显然,这是极端的例子。通常,即使我们希望做到这一点也不是很干净-您可能需要在目标环境中运行一些构建过程,因为您需要进行数据库更改。而且,如果您在版本之间具有非幂等数据库mod,那么无论使用哪种方法,回滚都不会那么容易,因为您需要回滚数据库(通常来说,尝试部署幂等数据库进行更改,然后在确定它们已超出应用程序流程之后,在以后的版本中删除过时的数据库位。到“使用git进行部署的不良做法?”通常来说,是“是”,就像使用训练轮对骑自行车不利。相对于反复地敲打屁股,这是一种进步,但希望最终将其淘汰。

评论


我也同意这一点。我不一定认为这很糟糕,但是还有其他一些令人关注的问题。 1.它将所有内容投入生产2. git checkout不是事务性的。这意味着在部署期间,在写入单个文件时,系统可能处于不一致状态。正如@siliconrockstar指出的那样,git是SCM系统,而不是部署系统。他们解决了两个不同的问题。

–凯文·施罗德(Kevin Schroeder)
18年11月28日在14:40

@siliconrickstar您对此有任何进一步的阅读或资源吗?我以前使用过此过程,但是我想查看一些最佳实践指南。例如,使用Gitlab,您的CI管道会将整个应用程序捆绑到一个zip中,然后将其重新同步到生产环境中吗?依赖关系以及所有依赖关系(例如供应商,node_modules等),或者它们将在服务器上解析(我假设是前者,因为您将应用程序的整个快照放在一个目录中,并且生产服务器没有做任何“工作”符号链接交换除外)

–克里斯
19年2月17日在1:28

@Chris我希望我能为您提供一些“权威”资源,但是实际细节会因项目和堆栈而异。如今,我主要与Magento一起工作,甚至他们使用Magento Cloud的“官方”部署流程也会做一些奇怪的事情,而这可能不是最佳实践(耦合分支和环境马上浮现在脑海)。在Magentoland中,关于依赖关系,当前的Magento使用composer和npm,以及IMO,通常可以放心地在部署目标上执行这些工具,而不是复制所有供应商/每个部署。

–siliconrockstar
19年9月4日在14:44

太酷了,谢谢@siliconrockstar!

–克里斯
19年9月5日,下午1:57

#4 楼

您可以在调用git clone时使用--separate-git-dir=<git dir>参数。这将在.git目录中放置一个符号链接(符号链接到Git,我认为这不是指向您的OS的符号链接),并且您可以将<git dir>指定到文档根目录之外的某个位置。

#5 楼

我之前采用的另一种方法类似于Terry Chia关于接收后挂钩的评论。多个不同的操作。

在Web文件夹以外的任何地方创建一个裸仓库。然后,可以将裸存储库用作要推送到的远程数据库,并且可以触发接收后挂钩以将新代码签出到指定目录中。充当一条“单向”街道,其中代码必须经过源代码控制才能最终投入生产。您可以将不同的分支/版本部署到不同的位置(全部来自同一裸仓库)。它还提供了一种使用标准git checkout进行回滚的简便方法。您必须手动执行git --work-tree=/path/to/code status才能看到任何更改(但无论如何您都不应该更改生产代码,对吧?)

评论


我认为您不需要该介绍性段落。它仅会试图将您的帖子标记为删除。更好地解决问题。

– techraf
16 Mar 29 '16 at 15:08

作为读者,当我看到“想发表评论”时,我通常会认为它没有用,并跳过阅读。您在这篇文章中有一些有用的内容。我会以此为基础。洗涤,漂洗并重复直到您有足够的声誉来发表评论。

–培根·布拉德
16 Mar 29 '16 at 20:23

感谢您的反馈!我删除了第一句话并扩大了答案。最终它太长了,无法发表评论。

– russdot
16 Mar 30 '16 at 0:33

#6 楼

我同意Terry Chia的观点,这是非常好的做法。它确保:


正确的修订是正确的,
包含所有需要的文件并检查版本的完整性,
使部署过程快速和简单

但是,我必须补充一点,我有一些需要分享的注意事项。
代码,
文档,
单元测试,
部署脚本,
集成工具,
.deb归档,
sql补丁
或类似的东西,也许还有很多其他东西

好,在生产中,您只需要代码!

,因为是文档,单元测试,工具或。 deb归档文件可能占用大量空间磁盘,并且与生产无关。

使用Subversion(1.7版之前),您可以仅检出src/目录,您将拥有所有优势。
但是在Subversion> 1.7和Git中,您不能这样做。
,但是您的项目/测试和project-src代码将无法同步,这真的很糟糕。

然后解决方案是使用“稀疏签出”,请参见:https:// /stackoverflow.com/questions/600079/how-do-i-clone-a-subdirectory-only-of-a-git-repository

因此可以使用git,但请注意这些缺点。

评论


我想介绍一下子模块\特殊结帐\其他怪异的东西,然后再做决定。通常,您的“其他东西”不是很大,因此可能是一个问题。当开发人员可以克隆整个存储库并立即开始处理它而无需在配置所有内容时进行魔术般的舞蹈时,情况会更好。附言当然,您根本不应该在您的存储库中存储二进制blob。

–教父
18年8月18日在23:47

#7 楼

这是我用来使git推送到prod的脚本。

https://gist.github.com/Zamicol/f160d05dd22c9eb25031

它假定已推送到master分支的任何内容均已准备就绪。所有其他推入的分支都将被忽略。您可以修改此钩子脚本以适合您的需求。

就您的担忧而言,我将git目录放在/ var / git下,并将生产文件放在其他位置(例如/ var / www),并进行限制访问这些目录。

您还可以将git repo与生产服务器放在单独的服务器上,然后在上面的脚本中使用scpssh之类的文件将文件从git服务器移至生产服务器。这将使您仍然可以使用git来推送产品,同时将代码与生产分开。