教程:将实时项目从 Forge 迁移到 Envoyer
发布日期:作者: Joost
一般来说,我会尽量减少使用付费服务。如果它们能带来显著价值,我会集成它们,因为作为一家自筹资金的创始公司,成本会迅速累积。我也会尽量减少服务器管理工作,因为它会让我变得暴躁。
最近,我将我的实时项目从 Forge 迁移到 Envoyer 进行部署。由于这些项目是实时应用,并被客户积极使用,我希望迁移过程尽可能无缝且停机时间尽可能短。
在这篇文章中,我想分享完成此操作的步骤。首先,我会解释我决定迁移的一些背景。如果您想深入了解迁移步骤,可以跳过第一部分。
背景
使用 Forge 进行部署大约需要 10 到 20 秒。我的项目有一个 API,流量越来越多,而且我每周都会发布几次更改,这很快就累积到我开始收到来自监控服务的停机时间通知。
我还想在部署过程中添加更多步骤,例如 npm ci
和 npm run production
,这会增加更多停机时间。
所以,是时候进行零停机时间部署了,这是 Envoyer 的主要卖点。但是,还有一些其他优势,它们也会为部署过程带来很大的价值,而且我之前没有真正想过。
如果出现问题(肯定会出现问题),您的应用程序不会一直处于维护模式
在部署脚本开始时使用 php artisan down
将应用程序置于维护模式,然后以 php artisan up
结束以将其从维护模式中取出,这很常见。
但是,如果在这两者之间出现问题,应用程序将保持在维护模式,因为它永远不会到达 php artisan up
。因此,您必须将应用程序从维护模式中取出,并调查出现问题的原因。使用 Envoyer,如果部署过程中的任何步骤出现故障,整个过程将被取消,您的应用程序仍然可以正常运行。
重新部署部署
如果您的应用程序在任何时候引入了 bug,您需要将其恢复到工作状态,只需单击一次,即可重新部署之前的部署。使用 Laravel Forge,您的生产环境将出现 bug,无法轻松回滚。
配置构建和部署步骤
虽然您可以使用 Forge 通过部署脚本执行此操作,但这总感觉像是在玩火。使用 Envoyer,一切变得轻松、有序且可拖放。
让您的生活更轻松
由于部署现在是零停机时间,您可以将更多步骤添加到这些部署中,这将使您的部署生活更轻松。例如,我有一些文件需要复制到 CDN。现在,我可以通过在部署过程中运行 artisan 命令来执行此操作,使用部署钩子。太棒了!
还有一些其他功能,例如健康检查和心跳,但这些是主要优势。让我们继续迁移。
步骤 1:基础知识
我不会详细介绍,因为这真的很简单。首先在 Envoyer 中执行以下操作:连接您选择的源代码管理(例如 Github)并创建一个项目。
提示:如果您想保存超过四个最近的部署,请转到您的项目 > 设置,并将保留的部署数量增加。
注意:以下步骤假设您在 Forge 中的网站目录设置为 /public,而不是其他目录。您可以通过转到 Forge 中的网站,然后转到侧边栏菜单中的元数据,然后转到网站目录来查看。如果您有 /public 之外的任何目录,请在执行后续步骤时牢记这一点。
步骤 2:导入您的 Forge 服务器
以前,这需要多个步骤,包括复制 IP 地址和添加 SSH 密钥,但是 Laravel 团队现在简化了这个过程。
- 转到 Forge 中的账户(右上角),从侧边栏菜单中转到 API,并创建一个令牌(可以将其命名为 Envoyer)。
- 然后,转到 Envoyer 中的账户(右上角),从侧边栏菜单中转到集成,并使用刚生成的令牌连接到 Forge。
- 转到您的项目,单击服务器,然后单击导入 Forge 服务器,并选择要导入的网站。
完成!
步骤 3:首次部署
现在,您可以真正开始部署了。不用担心,因为这次部署还不会生效,我们将在后面进行操作。但是,这将有助于您更好地理解底层原理,因为您可以查看旧文件结构和新文件结构。由于目前还没有任何内容生效,因此它是测试一切正常工作的一个好方法。
我们将在最后一步将我们的实时应用程序从 Forge 切换到 Envoyer。
步骤 4:了解新的文件结构
您的网站目录
让我们看看现在的情况。SSH 登录到您的 Forge 服务器,并转到您的网站目录(下面显示为 example.com)。它看起来像这样。
drwxrwxr-x 15 forge forge 4096 Dec 21 16:27 ./drwxr-xr-x 11 forge forge 4096 Dec 21 16:26 ../-rw-rw-r-- 1 forge forge 2417 Dec 15 22:04 .envdrwxrwxr-x 8 forge forge 4096 Dec 19 14:07 .git/-rw-rw-r-- 1 forge forge 111 Jul 3 19:12 .gitattributes-rw-rw-r-- 1 forge forge 214 Dec 9 15:30 .gitignore-rw-rw-r-- 1 forge forge 174 Jul 3 19:12 .styleci.yml-rw-rw-r-- 1 forge forge 1607 Nov 9 14:07 README.mddrwxrwxr-x 14 forge forge 4096 Nov 9 14:07 app/-rw-rw-r-- 1 forge forge 1686 Jul 3 19:12 artisan-rw-rw-r-- 1 forge forge 187 Jul 3 19:12 auth.jsondrwxrwxr-x 3 forge forge 4096 Jul 3 19:12 bootstrap/-rw-rw-r-- 1 forge forge 2850 Dec 16 13:32 composer.json-rw-rw-r-- 1 forge forge 396382 Dec 19 14:07 composer.lockdrwxrwxr-x 2 forge forge 4096 Dec 17 11:51 config/lrwxrwxrwx 1 forge forge 46 Dec 21 16:27 current -> /home/forge/example.com/releases/20201221152610/drwxrwxr-x 6 forge forge 4096 Nov 17 13:46 database/drwxrwxr-x 3 forge forge 4096 Jul 3 19:12 nova-components/-rw-rw-r-- 1 forge forge 450772 Dec 15 22:35 package-lock.json-rw-rw-r-- 1 forge forge 1059 Nov 17 13:46 package.json-rw-rw-r-- 1 forge forge 1405 Jul 3 19:12 phpunit.xmldrwxrwxr-x 11 forge forge 4096 Dec 19 14:07 public/drwxrwxr-x 9 forge forge 4096 Dec 21 16:26 releases/drwxrwxr-x 6 forge forge 4096 Jul 3 19:12 resources/drwxrwxr-x 2 forge forge 4096 Dec 19 14:07 routes/-rw-rw-r-- 1 forge forge 563 Jul 3 19:12 server.phpdrwxrwxr-x 7 forge forge 4096 Nov 9 14:39 storage/drwxrwxr-x 4 forge forge 4096 Jul 3 19:12 tests/drwxrwxr-x 67 forge forge 4096 Dec 19 14:07 vendor/-rw-rw-r-- 1 forge forge 683 Jul 3 19:12 webpack.mix.js
您在网站文件夹(example.com)中看到的是通过 Forge 部署的网站。
新的 Envoyer 目录
Envoyer 创建了两个新的目录。
current
文件夹是最新发布目录的符号链接。这就是部署的工作方式:创建一个新的发布目录,而 current 目录将链接到它。
releases
文件夹包含所有部署。文件夹的名称是时间戳。
新结构
如果您现在进入 current 目录,您会注意到两件事。
.env 链接回 /home/forge/example.com/.env
以及
/storage 链接回 /home/forge/example.com/storage
这意味着这些文件不会在每次部署时被覆盖,因此存储在 storage
中的文件和缓存将保持原样,当然,您的 .env
文件将保留在本地,供每次部署使用。
步骤 5:链接存储文件夹
这让我们进入步骤 5。请记住,当您第一次通过 Forge 部署时,您是否运行了 php artisan storage:link
?对于您通过 Envoyer 进行的新部署,也需要此链接。问题是,每次新的部署都会导致您不得不重新运行它,因为每次部署都是您应用程序的新副本,位于新的文件夹中。
幸运的是,Envoyer 提供了一个设置来永久设置此链接。转到您的项目,部署钩子,并单击管理链接文件夹。将 public/storage
链接到 storage/app/public
。
步骤 6:Horizon、调度程序和守护进程
如果您在 Forge 中设置了这些,您将知道它们是什么以及为什么要设置它们。它们运行在一个文件夹中,这个文件夹仍然是您 Forge 部署所在的“旧”文件夹。让我们将您需要的调度程序和守护进程添加到 Envoyer 文件夹中。
调度程序
在 Forge 中,转到您的服务器,对于每个调度程序,如果其路径包含 /home/forge/example.com
(其中 example.com 是您的网站),请复制这些调度程序,并创建一个新的调度程序,将路径中的 current
添加到路径中:/home/forge/example.com/current
。
例如,
php /home/forge/example.com/artisan schedule:run
将变为
php /home/forge/example.com/current/artisan schedule:run
之所以说复制,是因为您当前的应用程序(通过 Forge 部署)仍在运行,并使用调度程序。因此,请添加新的调度程序,一旦您完成了迁移到 Envoyer 的工作(本指南中的最后一步),您可以删除旧的调度程序。
注意:这些调度程序现在将在两个应用程序上运行(当前的 Forge 应用程序和新的 Envoyer 应用程序)。我没有遇到任何问题,但如果你有大量进程非常频繁地运行(例如,每分钟一次),那么请先检查你希望如何协调这些进程。例如,你可以先复制调度程序,并将部署作为最后一步执行。
守护程序
守护程序也是一样,其中 Directory 值应该是 /home/forge/example.com/current
这里也是:添加新的,不要更新现有的。
Laravel Horizon
如果你使用 Horizon,你可能在部署时运行 php artisan horizon:terminate
。你可以通过转到你的项目、部署钩子,然后选择添加钩子来将其添加到 Envoyer。
为其命名,以 Forge 身份运行,然后添加
cd {{ release }}php artisan horizon:terminate
第一行是为了确保它进入新部署的刚添加的目录中,以便在那里运行命令。
确保选择服务器并点击保存钩子。
步骤 7:我们上线了吗?
还没有,但让我们现在就做!我们现在可以将 Web 目录切换到新的 current
目录,该目录符号链接到最新版本。
在 Forge 中,转到你的网站,从侧边菜单中选择 Meta,然后转到 Web 目录。将此更新为 /current/public
。
恭喜,你现在拥有零停机时间部署。
额外步骤
删除旧文件
正如你可能已经发现的那样,现在你的应用程序在网站文件夹(**example.com**)中有一个未使用的副本,因为 Envoyer 部署在 **example.com/current** 中。这意味着你可以选择删除旧文件。
你可以删除所有内容,除了
- 文件夹 **current**
- 文件夹 **releases**
- 文件夹 **storage**
- 文件 **.env**
为什么我的 releases 文件夹没有像我在 Forge 上那样有一个 .git
文件夹?
在你的先前 Forge 部署中,有一个 .git 文件夹,因为 Forge 会从你的源代码控制存储库中拉取。Envoyer 不会这样做。相反,它会下载你仓库的 tarball,然后将其解压缩到相关的 releases 文件夹中。
添加部署钩子
我们已经简单地介绍过 Horizon,但你可以添加任何你喜欢的部署钩子。
诸如运行 npm ci
和 npm run production
之类的事情很有用,但你也可以创建自己的自定义 artisan 命令并在部署时运行它们。例如,一个清除 Redis 缓存中你自己的缓存项的命令。由于你现在拥有零停机时间部署,因此将这些内容移动到部署过程中非常方便。
希望这可以帮助你将你的生产应用程序从 Forge 迁移到 Envoyer。享受那些甜蜜的零停机时间部署!如果你想注册 Envoyer,你可以在这里这样做。
作者:Joost 来自 Freddy Feedback