资讯专栏INFORMATION COLUMN

deployer 实战经验分享

cangck_X / 2769人阅读

摘要:开发完项目,免不了要部署上线。进行部署的过程中,项目仍然能够正常访问。能十分方便地进行回滚。线上测试与生产使用的是青云的云主机,系统。或者想办法设置实现免密码登录。

开发完项目,免不了要部署上线。纯手动操作,登录、拉代码、改配置、清缓存、各种服务重启等等一条龙下来,人生宝贵的几分钟就过去了。而且手动操作十分容易出错,遗漏部分步骤都有可能产生一些邪门问题。所以我很早就开始寻求一种能轻松部署 Laravel 项目的办法。

laravel 的官方文档里介绍了 Envoy,之前用过,能满足大部分场景,但仍然有一些限制。直到后来看到了 deployer,大有相见恨晚之感!

deployer 的优势

真正解放双手,一条命令完成部署。

进行部署的过程中,项目仍然能够正常访问。部署成功完成后才切到新的版本。

能十分方便地进行回滚。

丰富任务钩子和预置任务可灵活的组合完成各种任务,比如执行前端依赖的安装、构建等。

其它骚姿势等你发掘……

使用 deployer 的前提条件

本地机器(也就是你执行 dep 命令时所在的机器)能够 SSH 连接到目标机器(代码要部署到的机器,不管是在线的云主机还是局域网中的虚拟机)

有登录目标机器并调整一些设置的权限,或者能让负责人协助调整。(使用过程中可能遇到问题需要调整一些设置,后面会提)

目标主机有拉取项目仓库的权限。(这个应该都有吧,不然玩个毛?)

足够大胆、足够细心、足够有耐性……

deployer 的使用

首先说明下个人实际使用场景。

本人使用 win10 系统,使用 Homestead 作为 PHP 项目的开发环境(vagrant v2.1.1, homestead v7.4.1, virtualbox v5.2.8, homestead 的 virtual box 版本为 v5.2)。

本地开发能完成绝大部分开发和测试任务,但在部署到生产机之前仍然需要先部署到开发机上进行测试。线上测试与生产使用的是青云的云主机,Ubuntu16 系统。

以下的操作都是在 homestead 虚拟机里进行操作!

安装

cd /path/to/your/project

composer require deployer/deployer --dev
个人习惯于将其作为项目依赖安装,当然也可以根据需要或个人喜好全局安装。

初始化 deployer 配置文件

vendor/bin/dep init

因为我用的是 laravel 输入项目类型 1 后回车,然后会出现一个让设置 git 仓库的,默认是对应项目的 git 远端仓库,不需要修改的话确认就可以了。

完成上面的初始化后,项目要目录下会出现一个 deploy.php 文件,deployer 的配置就靠它了。初始的配置如下,里面显示了一些基本的配置。

set("deploy_path", "~/{{application}}");    
    
// Tasks
// 这算是个自定义任务示例
task("build", function () {
    run("cd {{release_path}} && build");
});

// [Optional] if deploy fails automatically unlock.
// 如果部署失败,自动解除部署锁定状态,以免影响下次执行
after("deploy:failed", "deploy:unlock");

// Migrate database before symlink new release.
// 执行数据库迁移,建议删掉,迁移虽好,但毕竟高风险,只推荐用于开发环境。
before("deploy:symlink", "database:migrate");

修改配置

默认的配置肯定是不行的,目标主机啥的还不知道呢。下面直接贴上自己用到的配置,并加入了少量说明。

stage("production")
    ->user("root")
    ->port(22)
    ->set("branch", "master") // 最新的主分支部署到生产机
    ->set("deploy_path", "/data/wwwroot/xxx")
    ->identityFile("/home/vagrant/.ssh/id_rsa")
    ->forwardAgent(true)
    ->multiplexing(true)
    ->set("http_user", "www") // 这个与 nginx 里的配置一致
    ->addSshOption("UserKnownHostsFile", "/dev/null")
    ->addSshOption("StrictHostKeyChecking", "no");

// 测试用的主机
host("172.16.3.2")
    ->stage("debug")
    ->user("root")
    ->port(22)
    ->set("branch", "develop") // 一般是把 develop 分支弄到测试机测试,没问题再合并
    ->set("deploy_path", "/data/wwwroot/xxx")
    ->identityFile("/home/vagrant/.ssh/id_rsa")
    ->forwardAgent(true)
    ->multiplexing(true)
    ->set("http_user", "www")
    ->addSshOption("UserKnownHostsFile", "/dev/null")
    ->addSshOption("StrictHostKeyChecking", "no");

// 自定义任务:重置 opcache 缓存
task("opcache_reset", function () {
    run("{{bin/php}} -r "opcache_reset();"");
});

// 自定义任务:重启 php-fpm 服务
task("php-fpm:restart", function () {
    run("systemctl restart php-fpm.service");
});

// 自定义任务:supervisor reload
task("supervisor:reload", function () {
    run("sudo supervisorctl reload");
});

// 自定义任务:部署成功了用 bearychat 发消息给大佬和自己
task("send_message", function () {
    run("{{bin/php}} {{release_path}}/artisan deployed");
});

// 自定义任务:缓存路由,recipe/laravel.php 默认的流程里没有这个,所以加上,息看需要
after("artisan:config:cache", "artisan:route:cache");

// 执行自定义任务,注意时间点是 current 已经成功链向新部署的目录之后
after("deploy:symlink", "php-fpm:restart");
after("deploy:symlink", "supervisor:reload");

// 部署成功后重置 opcache 缓存
after("deploy:symlink", "opcache_reset");

// 部署成功后调用 laravel 命令行发送通知
after("success", "send_message");

// [Optional] if deploy fails automatically unlock.
after("deploy:failed", "deploy:unlock");

代码修改完成后运行部署

修改完成后记得先提交并将代码推送到远端仓库。然后执行如下命令进行部署:

vendor/bin/dep deploy debug // 部署到测试机

vendor/bin/dep deploy production // 部署到生产机

过程中如果提示要输入密码,则输入登录目标主机的密码。或者想办法设置 SSH key 实现免密码登录。

首次部署后设置 .env,并配置 nginx 站点

默认情况下,首次部署后,.env 文件是不会自动创建的,需要自己创建并修改,同时 nginx 站点配置也需要自己动手。对于 .env 文件,存放于目标主机的 /path/to/project/shared/ 目录下。

修改 .env 后记得重新缓存配置 php artisan config:cache

另外需要注意的是配置 nginx 站点时,网站根目录应该为 /path/to/project/current/public。如果使用 supervisor 之类的,相关的目录在配置时也要注意了。

部署后目录的结构及相关说明

在部署的目标目录下执行 ls -la,可以看到如下结果:

说明:

| projectname
    |--- @current -> releases/
    |--- .dep
        |--- releases 一个文本文件,里面存着各次部署的时间、次数序号(或者说版本号)信息
    |--- releases // 目录下根据配置保存近几次部署,更早的则会被自动清理
        |--- 1
        |--- 2
        |--- .
        |--- .
        |--- 
            |--- 目录中是项目的实际代码
            |--- 包括 .git, vendor, .env, storage ...
            |---  .env, storage 实际通过 symlink 链接到 shared 目录下对应的文件上
    |--- shared
        |--- storage // 即 laravel 项目的 storage 文件夹
        |--- .env // 即 laravel 项目的 .env

每次部署更新,会在 releases 下新建文件夹如 num,拉取对应的最新代码,安装 composer 依赖完成一些其它自定义任务,并将 storage, .env 链接到 shared 文件夹下的那两个上去,然后项目根目录下的 current 通过 syslink 链接到这个新文件夹 num 上,这算是其动作的基本原理,网站在部署过程中能继续访问也得益于此。

.env 和 storage 下的一些未加入代码库中的内部,部署时不会自动更新,因此有些情况下需要手动处理。

其它日常使用技巧

正常情况下,部署过程中 deployer 会自动完成缓存配置、清理已编译的缓存等任务。理论上我们不需要自己再动手,但需要时也可以手动执行

// 缓存路由
vendorindep artisan:route:cache production

// 缓存配置
vendorindep artisan:config:cache production

// 清视图缓存
vendorindep artisan:view:clear production

// 执行自定义任务,如前面提到的重新载入 supervisor
vendorindep supervisor:reload production

// ssh 连接到主机,hostname 也可以不输入,然后从选项里选
vendorindep ssh 

// 列出其它一些可用的命令
vendorindep list
可能遇到的问题
在 deploy 命令后加上 -vvv 选项可以输出详细错误信息,方便调试。

由于部分 php 函数被禁用而报错

目标主机 php.ini 里的 disabled_functions 项里配置了一些被禁用的函数,如果 deployer 用到了这些函数就可能报错,修改 php.ini 解除相关函数的禁用状态就可以了。

php 执行文件位置引起的错误

目标主要通过 apt-get 命令或 oneinstack 一类的一键包安装的 PHP,可执行文件通常在 /usr/local/php/bin/php,而 deployer 内使用 /usr/bin/env: php 形式调用,相当于 /usr/local/bin/php。这就可能出错,一般是报 command -v "php" failed。解决办法很简单,只要加个软链接就可以了。

ln -s /usr/local/php/bin/php /usr/local/bin/php

目录主机不在线或者网络连接问题

解决办法当然是打开目录主机并检查网络情况

关于缓存清理

deployer 的 laravel 默认部署流程中,会执行 php artisan cache:clear 命令,如果你的项目里使用了 redis 驱动的队列或者一些强依赖于缓存的业务逻辑(如缓存文章阅读数定期再入库),则需要进行一些骚操作了。

比如,你可以在 config/database.phpredis 项中为队列链接指定其它的 database。

或者修改 deploy.php 配置默认的缓存清理任务,跳过缓存清理动作。(通常并不建议这么做,因为项目的缓存,应该是可清理的,如果部分业务确实十分依赖于缓存,则应该考虑一些缓存持久化的实现了)

// 覆盖 recipe/laravel 里默认的 artisan:cache:clear 任务,部署时不清缓存
task("artisan:cache:clear", function () {
    return true;
});

原文地址

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/30751.html

相关文章

  • CI Weekly #6 | 再谈 Docker / CI / CD 实践经验

    摘要:阿里云效平台基于理念的私有平台实践本文将系统的从个方面,分享互娱运维团队对于运维平台实践经验及未来展望,希望对大家有一些参考意义。 CI Weekly 围绕『 软件工程效率提升』 进行一系列技术内容分享,包括国内外持续集成、持续交付,持续部署、自动化测试、 DevOps 等实践教程、工具与资源,以及一些工程师文化相关的程序员 Tips 。同步于 flow.ci Blog、微信公众号、官...

    justCoding 评论0 收藏0
  • Docker部署基于Nodejs的Web应用-实战

    摘要:采用虚拟化的技术来虚拟化出应用程序的运行环境。安装成功后,可以通过查看版本号尽量使用最新的稳定版本。是镜像名,是镜像的版本号,到此你已经成功构建了一个新的镜像,你可以通过,查看你的镜像。部署时将此文件到生产环境服务器上。 Docker docker是一个开源的应用容器引擎,可以为我们提供安全、可移植、可重复的自动化部署的方式。docker采用虚拟化的技术来虚拟化出应用程序的运行环境。此...

    marek 评论0 收藏0
  • Docker部署基于Nodejs的Web应用-实战

    摘要:采用虚拟化的技术来虚拟化出应用程序的运行环境。安装成功后,可以通过查看版本号尽量使用最新的稳定版本。是镜像名,是镜像的版本号,到此你已经成功构建了一个新的镜像,你可以通过,查看你的镜像。部署时将此文件到生产环境服务器上。 Docker docker是一个开源的应用容器引擎,可以为我们提供安全、可移植、可重复的自动化部署的方式。docker采用虚拟化的技术来虚拟化出应用程序的运行环境。此...

    mikasa 评论0 收藏0
  • SegmentFault D-Day 上海站回顾:新热技术与项目实战

    摘要:上海站今天顺利进行了,沙龙的四位重量级的嘉宾都和大家分享了深度有趣的是技术内容和别具一格的圆桌讨论,从深入实践,到的产品化实战经验,再到最近新热的和,是一场真正的技术实战经验分享。上海站嘉宾分享文档及圆桌讨论 SegmentFault D-Day 2015 上海站 今天顺利进行了,沙龙的四位重量级的嘉宾都和大家分享了深度有趣的是技术内容和别具一格的圆桌讨论,从 API 深入实践,到 N...

    fireflow 评论0 收藏0
  • fir.im weekly - 「 持续集成 」实践教程合集

    摘要:来这里看看的工程师如何进行持续集成与持续部署。主要介绍了豆瓣移动持续集成和测试相关实践,用工具化自动化社会化测试来解决遇到的问题,将打包发布环节自动化。这期的持续集成实践分享就到这里。 我们常看到许多团队和开发者分享他们的持续集成实践经验,本期 fir.im Weekly 收集了 iOS,Android,PHP ,NodeJS 等项目搭建持续集成的实践,以及一些国内外公司的内部持续集成...

    A Loity 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<