在构建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 有回滚更改的方法,如果出现错误可以恢复到以前的版本,所以如果你的需要可以链接到之前的版本。这可能需要更复杂的设置,但我会觉得这很有趣。
无论如何,我对目前的成果很满意,尽管我仍想对其进行改进。如果您想了解未来的改进,请 关注我的推特,我可能会在那里发布任何更新。
driesvints, cosmeoes 赞同了这篇文章