支持 Laravel.io 的持续发展 →

零 downtime 部署适用于 Laravel 应用

20 Feb, 2022 5 min read

在构建laravelremote.com(一个Laravel远程工作聚合器)时,我担心每次我想将一些更改推送到生产服务器时,网站可能会宕机几秒钟。这可能不是什么大问题,但我还是想避免这种情况。

Laravel提供了一款付费的第一方产品来避免这种情况,Envoyer,每月仅需10美元。但是,laravelremote.com目前没有产生任何收入,我喜欢自己动手做事情来学习它的工作方式,并且我也喜欢它提供的自由。

因此,我想出了一个免费实现它的方法,并希望有人觉得这个方法有用。

理论

我在网上搜索了Envoyer的内部工作原理,虽然我不记得在哪里见过这个方法,但基本原理是这样的

我们有三个与项目相关的目录

  • releases/
  • current/
  • storage/

每次我们需要将网站更改部署上线时,都会在releases/目录下创建一个新的目录。然后,我们运行一些“设置”命令(例如:composer install、移动缓存路由、视图等),并将发布存储目录的符号链接添加到“永久”的storage/目录,因为我们不希望每次部署时忘记会话和类似的东西。完成所有这些操作后,我们将符号链接添加到current/目录,该链接指向我们刚刚创建的新版本。

这篇文章不是关于如何部署 Laravel 应用的教程,所以我不打算解释我的 NGINX 配置。你唯一需要知道的是,我的 NGINX 服务器配置为从/var/www/laravelremote.com/目录读取我的网站。此目录下还有一个符号链接,指向current/目录。

简单来说,每发布一个新的版本,都会将其链接到当前目录,这将使服务器显示更新。

实践

让我们将其付诸实践,首先我创建了一个基础目录,该目录将包含项目所需的所有内容。我喜欢将其添加到主目录下,并以应用名称命名

mkdir laravelremote/

由于我们将在该目录下工作,我们应该将其作为当前工作目录

cd laravelremote

现在我们需要创建存储目录和其他 Laravel 所需的子目录。

mkdir storage/
mkdir -p storage/cache/data/
mkdir storage/sessions/
mkdir storage/views/

这些都是存储目录中存在的默认 Laravel 目录。

之后,我们需要创建发布文件夹。

mkdir releases/

此外,我们还应该创建和全局的.env文件,并将其链接到每个发布上。

touch .env

向此文件添加生产环境变量。

当前目录将在我们第一次部署项目时创建,因此现在无需创建它。

部署

我们可以在发布目录下创建一个新的目录,从 GitHub 拉取主分支,运行所有其他需要的命令,然后将所有内容链接到当前目录。但是,对于简单的部署来说,这似乎是很多步骤,所以我想创建一个 bash 脚本来代替

#!/bin/sh

UNIX_TIME=$(date +%s)

DEPLOYMENT_DIRECTORY=$UNIX_TIME

mkdir -p $DEPLOYMENT_DIRECTORY
git clone --depth 1 --branch master [email protected]:username/reponame.git $DEPLOYMENT_DIRECTORY

echo removing storage
rm -Rf $DEPLOYMENT_DIRECTORY/storage

cd $DEPLOYMENT_DIRECTORY

cp ~/laravelremote/.env .env

echo link master storage
ln -s -n -f -T ~/laravelremote/storage ~/laravelremote/releases/$DEPLOYMENT_DIRECTORY/storage

composer install --no-dev
npm install
npm run prod

echo view:cache command
php artisan view:cache

echo route:cache command
php artisan route:cache

echo config:cache command
php artisan config:cache

echo migrations
php artisan migrate --force


cd ..

#link to the latest deployment from Live
ln -s -n -f -T ~/laravelremote/releases/$DEPLOYMENT_DIRECTORY ~/laravelremote/current

echo Done!

此脚本位于releases/文件夹中。它创建一个新的目录以存放新发布的当前 UNIX 时间戳,然后在该目录中将 GitHub 上的回购拉取到该目录中。之后,我删除了该目录中的存储文件夹,复制包含生产密钥的.env文件(你可能会想创建一个符号链接),然后将“永久”存储文件链接到当前发布。

最后,我运行了项目运行所需的必要命令。

  • 安装 composer 依赖项
  • 安装 NPM 依赖项并构建资源。(我不提交我的构建资源,其他人可能会做不同的事情)
  • 缓存视图、路由和配置以优化
  • 运行数据库迁移

然后最后,我们将当前目录链接到这个发布,这将发布更改。

就这么多,每次我向主分支推送东西时,我都会通过ssh连接到服务器,然后运行此脚本,我的更改即可零宕机部署。

可能的改进

我对这种方法的某些方面仍不满意。其中之一是我希望让它自动部署更改,不必 ssh 登录服务器即可将更改推送到 GitHub。另一个问题是旧版本不会被自动删除,目前我手动删除它们,但我也希望自动化这部分。顺便说一下,我发现 Envoyer 有回滚更改的方法,如果出现错误可以恢复到以前的版本,所以如果你的需要可以链接到之前的版本。这可能需要更复杂的设置,但我会觉得这很有趣。

无论如何,我对目前的成果很满意,尽管我仍想对其进行改进。如果您想了解未来的改进,请 关注我的推特,我可能会在那里发布任何更新。

最后更新 1 年前。

driesvints, cosmeoes 赞同了这篇文章

2
喜欢这篇文章? 让作者知道并给予他们掌声!

你可能还喜欢以下文章

March 11th 2024

如何使用 Larastan 将您的 Laravel 应用从 0 到 9 升级

在使用 Larastan 检测 Laravel 应用在执行之前存在的错误是可能的,因为...

阅读文章
July 19th 2024

无需 traits 标准化 API 响应

我观察到大多数用于 API 响应的库都使用 traits 实现...

阅读文章
July 17th 2024

通过 Discord 通知在 Laravel 项目中收集反馈

如何在 Laravel 项目中创建反馈模块,并在收到消息时收到 Discord 通知...

阅读文章

我们感谢这些 令人惊叹的公司 支持

您的标志在这里?

Laravel.io

问题解决、知识共享和社区建设的 Laravel 门户。

© 2024 Laravel.io - 版权所有。