终结!这可能是目前最好的 PHP 部署工具了
提问:怎么把大象放进鲸鱼里?
开过一些坑,写过一些有意思的 PHP 的程序或小工具。说实话,我是真的挺喜欢 PHP 这门语言的。 她开发迅速,很快就能将突然之间产生的灵感做出来。
有了几台学生机后,我便尝试着把自己写的东西都放到上面去。凭借着 Docker,管理起来还算是“整齐有序”。 都说程序员会想尽办法偷懒,“偷懒”也一定程度上也决定了生产力。 确实是这样的。 过去的很长一段时间里,我都在寻找一个优雅的部署 PHP 程序到服务器上的解决办法。特别是部署到 Docker 容器里。
网上其实有人给出一些比较“暴力”的解决方案:强行用 PHP 写一个 Webhook,里面使用exec()
来执行 Shell。从而做到拉取 Git 远程仓库等操作。
我一直是对exec()
eval()
这类函数十分反感的,会尽可能的避免去使用它们;究其原因就是太不安全了!因此有很多网站就会在 PHP 的配置文件中禁用这些危险的函数。
终于,在经过昨天一天的尝试踩坑,我总算解决了这个一直以来的痛点:
使用 GitHub 上的开源项目Deployer
来实现 PHP 的部署。https://github.com/deployphp/deployer
先聊聊我的看法
我最先是在 v2ex 上了解到 Deployer 的。
Deployer 也是使用 PHP 编写的。其中确实也使用了exec()
函数。但她是在命令行里运行的,因此……感觉还好吧……(真香
同时 Deployer 广泛支持多种主流的 PHP 框架,比如 Laravel、CodeIgniter、Symfony 等。(ThinkPHP 那垃圾国产框架压根连个 Logo 都没有,就别出来丢人现眼了
与此同时,Deployer 的部署任务还支持 Composer 依赖的安装,可以说是很舒服了。
但美中不足的是,作为 GitHub 上一个拥有 6k+ stars 的项目,Deployer 的文档质量真的是不敢恭维——在很关键的地方有错误,并且给的 example 也不是很详细。甚至还有些条目内容居然是 TODO! 瑕不掩瑜,这些小缺点并不妨碍我推荐她,不少会踩的坑我已经踩了一遍了。只要注意下就好。
那么,开始吧!
First of all
我这里用一个实际的例子来说明:将我之前写的小工具框架——Cube 部署到我腾讯云的学生机上。 其中会有用到 Docker,这是网上相关的教程所没有涉及的。
安装
curl -LO https://deployer.org/deployer.phar
mv deployer.phar /usr/local/bin/dep
chmod +x /usr/local/bin/dep
安装完成后,命令行输入:
dep -V
来检验是否安装成功。
初始化Deployer
在你准备实现部署的文件夹中,命令行输入:
dep init
之后跟随提示进行设置。
第一步选择项目类型,因为我这是自己写的 PHP 项目,所以选择0 - Common
就好了。
初始化成功后,在当前目录下会多出一个deployer.php
的文件,这就是我们部署所使用的配置文件。
修改配置文件
首先,我们来大致梳理下通常一个 PHP 部署任务所要做的几件事情:
- 保存当前已经部署好的版本,以便之后玩脱了可以回滚。
- 从远程 Git 仓库拉取代码。
- 删掉之前的代码,将新的代码文件放到生产环境的文件夹里。
- 将一些文件换成生成环境下的,比如
config.php
文件,Laravel 框架下的.env
文件等。 - 调用 compsoer 下载依赖包
- 删掉临时的文件
- 完成
这些任务,Deployer 都支持!让我们一步一步来配置:
设置项目名称
// Project name
set('application', 'Cube');
设置远程 Git 仓库地址
// Project repository
set('repository', 'https://github.com/wuhan005/Cube.git');
如果是私有仓库的话,还请输入用户名与密码。Deployer 也是支持公钥的,这个还请自行查阅官方文档。
共享的文件/文件夹
// Shared files/dirs between deploys
set('shared_files', ['./core/database/Cube.db']); //文件
set('shared_dirs', ['./public/Module']); //文件夹
这里就是上面部署步骤中提到的第四点。
就我 Cube 这个项目而言,她是使用 SQLite 作为数据库,因此相对应的.db
数据库文件应该在每次部署中被保留下来。同时,她里面是存放着我写的小工具,因此包含着小工具的文件夹Module
也应该被保留。
部署的位置&文件夹链接形式
set('use_atomic_symlink', false);
set('use_relative_symlink', true); //软链接使用相对路径
set('deploy_path', '.'); //部署目录为当前目录下
Deployer 部署后生成的目录结构是这样的:
.
├── current -> releases/11
├── deploy.php
├── releases
└── shared
其中,releases
文件夹中包含了当前以及历史的版本,每个版本放在对应数字的文件夹里,方便你回滚。Deployer 默认会保存最近 5 次的部署版本,你可以在配置文件中进行设置。
而重点就是这个current
文件夹,她就是你当前版本的文件所在的文件夹,即站点的根目录。之后我们也要修改 Nginx 配置中站点根目录为current
文件夹。
注意,这里current
文件夹是通过软链接
的形式连接到releases
文件夹中的当前版本。而不是采用复制的方式。
Linux 菜鸡的我还专门去查了下软链接,顺便问了下部长。
**这个时候就可以把你想要共享的文件放到shared
文件夹下了。**注意要创建与项目里一样的目录结构。
设置要执行的任务
// Tasks
desc('Deplo project');
task('deploy', [
'deploy:info',
'deploy:prepare',
'deploy:lock',
'deploy:release',
'deploy:update_code',
'deploy:shared',
'deploy:writable',
'deploy:vendors', //composer 安装依赖包
'deploy:clear_paths',
'deploy:symlink',
'deploy:unlock',
'cleanup',
'success'
]);
这边其实不用做太多的改动,如果你的项目不需要 composer,或者没有composer.json
文件,可以去掉 'deploy:vendors'
这一步。
配置完成
到此配置文件Deploy.php
就完成了,附上我完整的配置:
<?php
namespace Deployer;
require 'recipe/common.php';
// Project name
set('application', 'Cube');
// Project repository
set('repository', 'https://github.com/wuhan005/Cube.git');
// [Optional] Allocate tty for git clone. Default value is false.
set('git_tty', true);
// Shared files/dirs between deploys
set('shared_files', ['./core/database/Cube.db']);
set('shared_dirs', ['./public/Module']);
// Writable dirs by web server
set('writable_dirs', []);
set('allow_anonymous_stats', false);
// Hosts
set('use_atomic_symlink', false);
set('use_relative_symlink', true);
set('deploy_path', '.');
// Tasks
desc('Deplo project');
task('deploy', [
'deploy:info',
'deploy:prepare',
'deploy:lock',
'deploy:release',
'deploy:update_code',
'deploy:shared',
'deploy:writable',
'deploy:vendors',
'deploy:clear_paths',
'deploy:symlink',
'deploy:unlock',
'cleanup',
'success'
]);
// [Optional] If deploy fails automatically unlock.
after('deploy:failed', 'deploy:unlock');
好诶!
到此为止就完成了!ヽ(✿゚▽゚)ノ好耶 命令行运行:
dep deploy
来执行部署吧!
可以看到 Deployer 很整齐很有序的部署好了我们的项目。 Enjoy it!
总结一下吧
可以说是完成了一件大事啊。现在部署起来可就轻松许多了,直接上服务器一行命令搞定。如果今后能做成 Webhook 加到 GitHub 上就更棒了! 我对 Deployer 这个项目也是挺感兴趣的,虽然她的功能强大,但是我对她的实现大概有个概念;有空的时候可以去研究下她的源码。 或者说……帮她改一下文档中的错误,翻译个中文文档也行啊嘻嘻嘻。(这人又想蹭 contributors 了
喜欢这篇文章?为什么不打赏一下呢?