Rocketeer:部署 PHP 應用程式的終極工具

WBOY
發布: 2023-08-30 14:22:01
原創
1074 人瀏覽過

Rocketeer:部署 PHP 应用程序的终极工具

曾經有一段時間,PHP 開發人員必須使用針對一般 Web 應用程式的部署工具。例如,您可以在 Johannes Schickling 的有關使用 Capistrano 部署 Laravel 應用程式的教程中看到這一點。它是一個 Ruby 工具,您需要編寫 Ruby 程式碼。這些工具可以完成工作,但與 PHP 應用程式的整合有限。這可能會導致某些場景的解決方案很糟糕。

但如今,我們很幸運擁有一些用我們的語言編寫的部署工具,可以實現更深入的整合。 Rocketeer 就是其中一個工具,它的靈感來自 Capistrano 和 Laravel 框架。

#Rocketeer 是一款現代工具,可為您的部署需求提供出色的方法。即跨不同環境和伺服器運行任務並管理應用程式。最重要的是,它還有一些魔力,例如如果偵測到 composer.json 檔案則安裝 Composer 依賴項。對於現代 PHP 應用程序,您可以獲得健全的預設設定和常見任務的自動化。而且您可以自訂和擴展一切。

#您可以將其描述為在客戶端執行的 SSH 任務執行程式。這些命令透過 SSH 連線在伺服器上執行。不幸的是,如果您使用僅具有 FTP 存取權限的共享託管供應商,那麼您就不走運了。您還需要一個遠端儲存庫,該工具可以從中取得您的程式碼。預設支援 Git 和 SVN。需要另一個版本控制系統的支援?使用提供的介面編寫您自己的實作。

#安裝

您可以透過兩種不同的方式安裝 Rocketeer。您可以下載 phar 檔案並使其可執行,或透過 Composer 安裝它。我是後者的支持者。將其作為依賴項可以在克隆存儲庫時輕鬆安裝。這可以使任何克隆存儲庫以使其啟動並運行的人受益。

#使用 Composer 安裝:

$ composer require anahkiasen/rocketeer --dev
登入後複製

我不建議您全域安裝它。將其保留在儲存庫層級將確保每個部署人員都運行相同的版本。我建議您將 vendor/bin 添加到您的 PATH 中。然後,您可以透過在專案根目錄中輸入 rocketeer 來使用該二進位檔案。

點火

讓我們開始吧!首先引導目錄和檔案進行設定。您可以透過在專案根目錄中執行 rocketeer ignite 來完成此操作。

#當您的應用程式啟動時,該工具會在您的專案中建立一個 .rocketeer 資料夾。該目錄的內容將如下所示:

| .rocketeer
| -- config.php
| -- hooks.php
| -- paths.php
| -- remote.php
| -- scm.php
| -- stages.php
| -- strategies.php
登入後複製

這些是開始設定部署所需的所有設定檔。每當我從這裡開始引用設定檔時,它都存在於 .rocketeer/ 目錄中。

#遠端資料夾結構

了解 Rocketeer 如何在伺服器端管理其資料夾結構非常重要,因為它與常規設定有點不同。它使用一些目錄來管理部署的某些方面,因此它可以有效地完成其工作。您指定要在伺服器上部署應用程式的路徑,該工具將處理其餘的內容。如果您將 /var/www/app 作為應用程式目錄,則該資料夾將如下所示。

| /var/www/app
|  | -- current => /var/www/app/releases/20160103183754
|  | -- releases
|  |  | -- 20160101161243
|  |  |  |-- uploads => /var/www/app/shared/uploads
|  |  | -- 20160103183754
|  |  |  |-- uploads => /var/www/app/shared/uploads
|  | -- shared
|  |  | -- uploads
登入後複製

最重要的資料夾是 current,它指向您的最新版本。這就是您的 Web 伺服器的文檔根目錄應設定的位置。那麼部署時會發生什麼事?

  1. 該工具會在 releases 目錄中建立一個帶有時間戳記的資料夾。
  2. 完成所有任務以準備發布。
  3. 將符號連結 current 更新為新版本。

此程序可讓您的部署對使用者透明。版本之間的切換幾乎是即時的,通常稱為原子部署。

有些資料應該在您的部署之間保持不變。例如,這可以是文件上傳、使用者會話和日誌。這些檔案或資料夾進入 shared 目錄。該工具會在每個版本中為您配置的版本建立符號連結。

活動

事件驅動工具,所有策略和任務在執行時都會在事件之前之後觸發。當任務失敗時,它們還提供特殊的暫停事件。例如,對於一般失敗,這可能是 dependency.haltdeploy.halt。這使我們能夠在需要的地方掛鉤流程。

部署期間發生的預設事件是:

  • deploy.before:在任何事情发生之前。
  • create-release.before:在创建新的发布目录之前。
  • create-release.after:创建新的发布目录后。
  • dependency.before:在安装或更新依赖项之前。
  • dependency.after:安装或更新依赖项后。也许请确保供应商文件夹中的二进制文件是可执行的。
  • test.before:运行测试之前。
  • test.after:运行测试后。
  • migrate.before:运行数据库迁移之前。也许您想备份数据库?
  • migrate.after:运行数据库迁移后。
  • deploy.before-symlink:在将版本符号链接为当前版本之前。
  • deploy.after:已完成。您可以通知人们一切顺利或其他情况。

我们还可以创建自己的事件,我们可以触发和监听这些事件。目前,我们将坚持为我们提供的这些事件。现在它们对我们来说就足够了。

任务

在 Rocketeer 的核心,我们发现了一个名为“任务”的概念。幕后发生的大部分事情都是核心任务。任务的定义可以是作为部署中的步骤执行的一组指令。如果我们查看该工具提供的一些类,我们可以大致了解什么是任务:诸如 DeploySetup迁移、 class="inline">回滚 和 class="inline">依赖项。当您部署时,部署命令本身就是一个带有子任务的任务。

任务类型

在这里,您将开始了解该工具与 PHP 的集成程度,因为您将用该语言编写任务。您可以通过三种不同的方式创建自己的任务:

任意终端命令。这些是您想要在服务器上运行的单行代码。对于很多事情都很有用,例如运行 gulp build ---development

关闭。如果您需要更多的灵活性或复杂性,您可以将任务编写为闭包(匿名函数)。假设您想在部署期间为 API 生成文档。

function($task) {
    return $task->runForCurrentRelease('apigen generate  source src  destination api');
}
登入後複製

课程。对于更复杂的任务,您应该利用该选项为任务创建类。您创建一个类并扩展 Rocketeer\Abstracts\AbstractTask。然后,您必须至少提供说明和 execute() 方法。这是一个完全无用的示例,只是为了显示任务类的结构:

namespace MyDeployableApp\Deploy\Tasks;

class HelloWorld extends \Rocketeer\Abstracts\AbstractTask
{
    /**
     * Description of the Task
     *
     * @var string
     */
    protected $description = 'Says hello to the world';

    /**
     * Executes the Task
     *
     * @return void
     */
    public function execute() {
        $this->explainer->line('Hello world!');

        return true;
    }
}
登入後複製

请注意,您必须自己注册任务类。您可以通过 hooks.php 文件执行此操作,并将其添加到 custom 数组...

'custom' => array('MyDeployableApp\Deploy\Tasks\HelloWorld',),
登入後複製

...或者您可以通过外观来做到这一点:

Rocketeer::add('MyDeployableApp\Deploy\Tasks\HelloWorld');
登入後複製

注册后,就可以执行它:

$ rocketeer hello:world
staging/0 | HelloWorld (Says hello to the world)
staging/0 |=> Hello world!
Execution time: 0.004s
登入後複製

定义任务

我们首先讨论事件,因为我们将任务挂接到流程中需要它们的地方。您可以通过几种方式来做到这一点。选择您喜欢且满足您的复杂程度要求的一个。

定义任务的最简单方法是在 hooks.php 文件中。它为此提供了两个数组,指定在某些事件之前或之后执行任务。

'before' => [
    'setup' => [],
    'deploy' => ['hello:world'],
    'cleanup' => [],
],
登入後複製

策略

您可能已经知道所提供的任务非常通用。以 依赖项 为例。我们谈论的是哪种依赖关系以及哪个包管理器?

这就是策略发挥作用的地方。策略是任务的具体实现,例如使用 Behat 运行测试或使用 Gulp 构建前端。任务有一个默认策略,可以选择通过 CLI 运行其他策略。我们可以这样列出可用的策略:

$ rocketeer strategies
+--------------+----------------+-----------------------------------------------------------------------+
| Strategy     | Implementation | Description                                                           |
+--------------+----------------+-----------------------------------------------------------------------+
| check        | Php            | Checks if the server is ready to receive a PHP application            |
| check        | Ruby           | Checks if the server is ready to receive a Ruby application           |
| check        | Node           | Checks if the server is ready to receive a Node application           |
| deploy       | Clone          | Clones a fresh instance of the repository by SCM                      |
| deploy       | Copy           | Copies the previously cloned instance of the repository and update it |
| deploy       | Sync           | Uses rsync to create or update a release from the local files         |
| test         | Phpunit        | Run the tests with PHPUnit                                            |
| migrate      | Artisan        | Migrates your database with Laravel's Artisan CLI                     |
| dependencies | Composer       | Installs dependencies with Composer                                   |
| dependencies | Bundler        | Installs dependencies with Bundler                                    |
| dependencies | Npm            | Installs dependencies with NPM                                        |
| dependencies | Bower          | Installs dependencies with Bower                                      |
| dependencies | Polyglot       | Runs all of the above package managers if necessary                   |
+--------------+----------------+-----------------------------------------------------------------------+

登入後複製

制定自己的策略

假设您正在为您的应用程序使用 BDD With Behat,而不是 TDD。然后您想使用 Behat 而不是 PHPUnit 来运行测试。由于它是一个测试运行程序,因此已经有一个策略命名空间,但没有实现。创建目录 .rocketeer/strategies/ 并将新的 BehatStrategy.php 放入其中。

namespace MyDeployableApp\Deploy\Strategies;

use Rocketeer\Abstracts\Strategies\AbstractStrategy;use Rocketeer\Interfaces\Strategies\TestStrategyInterface;

class BehatStrategy extends AbstractStrategy implements TestStrategyInterface
{
    public function test() {
        return $this->binary('vendor/bin/behat')->runForCurrentRelease();
    }
}
登入後複製

您现在可以将测试策略切换到 strategies.php 中的新实现。

'test' => 'Behat',
登入後複製

连接和阶段

您是否拥有或已经考虑过基础设施并不重要。如果您的应用程序部署到许多服务器上的许多环境中,这并不重要。火箭人将随时为您服务。您甚至可以在同一服务器上拥有许多不同的位置。这就是术语“连接”和“阶段”的用武之地。

连接是您部署应用程序的服务器。这通常称为环境,生产和登台就是这样的例子。在该工具中配置这些连接是轻而易举的事。您可以通过嵌套数组或为每个连接保留单独的文件来完成此操作。每个连接中还可以有多个服务器。

阶段就像连接中的连接,一种“连接感知”。您可以使用阶段在单个服务器上设置暂存和生产环境。因此,您将拥有一个包含两个阶段的连接,而不是两个单独的连接。

插件

一个很棒的功能是我们可以使用插件扩展我们的流程。有一些官方的可以与 Laravel、Slack、HipChat 和 Campfire 集成。 Packagist 上也有一些,但不是很多。通过 CLI 安装插件是一项简单的任务:

$ rocketeer plugin:install rocketeers/rocketeer-slack
登入後複製

尽管插件数量有限,但为将来开发插件留下了空间。它讲述了一个很好的哲学。为什么不开发自己的一款呢?

设置您的部署

为了让您的应用程序启动,您需要一些基本配置。您需要告诉 Rocketeer 在哪里可以找到您的应用程序以及应该将其部署到哪里。首先,我们在 config. 中设置应用程序名称并配置生产服务器。

'application_name' => 'my-deployable-app',

// [...]

'connections' => [
    'staging' => [
        'host' => 'staging.my-deployable-app.com',
        'username' => '',
        'password' => '',
        'key' => '/Users/niklas/.ssh/id_rsa',
        'keyphrase' => '',
        'agent' => '',
        'db_role' => true,
    ],
    'production' => [
        'host' =>
        'www.my-deployable-app.com',
        'username' => '',
        'password' => '',
        'key' => '/Users/niklas/.ssh/id_rsa',
        'keyphrase' => '',
        'agent' => '',
        'db_role' => true,
    ],
],
登入後複製

您现在拥有应用程序名称和用于部署应用程序的服务器。此设置使用 SSH 密钥身份验证,但您也可以使用用户名和密码进行连接。要提示输入用户名和密码,请设置 'key' => ''。该工具会将凭据存储在您的本地计算机上,并在以后每次使用它们。我不建议在配置文件中设置用户名和密码,因为您永远不希望将凭据提交到您的存储库。

您现在应该做的是更改部署到的默认连接。将默认设置设置为生产并不理想。您不想意外地部署到生产中。因此,在同一文件中,查找 default 键并将值更改为 staging

'default' => ['staging'],
登入後複製

应用程序名称本身并不那么重要。但如果您没有指定要部署到的文件夹,它将使用它作为根目录中的文件夹名称。默认情况下,根目录设置为 /home/www。使用此应用程序名称,它将部署到 /home/www/my-deployable-app。如果您想更改根目录,可以在 remote. 中进行更改。

// Deploys to /var/www/my-deployable-app/
'root_directory' => '/var/www/',
登入後複製

在同一文件中,您可以覆盖应用程序名称并为应用程序指定目录。

// Deploys to /var/www/tutsplus-tutorial
'app_directory' => 'tutsplus-tutorial',

登入後複製

现在您已经有了部署的接收端,但您还需要设置代码的位置,以便可以提取它。您可以通过在 scm.php 中设置远程存储库来执行此操作。默认情况下它使用 Git,但它也支持 SVN。您告诉它我们的存储库的地址,并在需要时提供凭据。我建议您在这里也使用 SSH 密钥身份验证,并将用户名和密码留空。

'repository' => 'git@github.com:owner/name.git',
'username'   => '',
'password'   => '',
'branch'     => 'master',
登入後複製

由于您添加了到生产服务器的连接,因此您想要部署 master 分支。

连接和阶段特定配置

在大多数情况下,您不希望所有连接或阶段都使用相同的配置选项。例如,您想要将另一个分支部署到临时环境。 Rocketeer 允许您使用 config.php 覆盖连接和阶段的配置值。要在暂存连接上部署名为“暂存”的分支,请执行以下操作:

'on' => [
    'connections' => [
        'staging' => [
            'scm' => [
                'branch' => 'staging',
            ]
        ]
    ],
],
登入後複製

它使用嵌套数组来覆盖配置值。在 staging 键下,找到要更改的文件中的相应键。在本例中,它是 branch,位于 scm.php

部署,起飞!

现在您已完成成功部署所需的一切设置。您尚未满足完整部署的要求,但足以将应用程序克隆到服务器并提供给最终用户。首先,您可以执行检查策略来查看您的服务器是否满足要求。

$ rocketeer check
登入後複製

如果一切正常,您可以通过运行进行部署:

$ rocketeer deploy
登入後複製

由于这是您的第一次部署,Rocketeer 将确保一切都达到标准。该工具创建它所需的目录以及我们的应用程序将驻留在其中的目录。如果一切顺利,您应该在服务器上拥有完整的应用程序构建。

如果您在上一节中将默认连接更改为暂存,则它将始终部署到暂存。当然,除非您告诉它部署到其他地方。当您想要在不同的连接或多个连接上进行部署时,可以使用 --on 开关。

# Deploy to production
$ rocketeer deploy --on="production"

# Deploy to staging and production
$ rocketeer deploy --on="staging,production"
登入後複製

想看看按下按钮后您的服务器上会发生什么吗?使用 --pretend 标志让该工具告诉您它将在服务器上执行什么。

$ rocketeer deploy --pretend
登入後複製

休斯顿,我们遇到了问题。我们需要回滚。

不幸的是,我们需要处理会破坏功能或对基础设施造成严重破坏的部署。然后您需要快速回滚到最新版本。幸运的是,这是一个简单的操作 - 只需运行命令:

$ rocketeer rollback
登入後複製

由于它存储了许多构建,因此执行回滚速度很快。它将 current 的符号链接更改为以前的版本。

共享目录

设置共享目录很简单 - 只需将它们添加到 shared 数组(位于 remote.php 中)。 Rocketeer 将在之后的部署中为您创建并链接这些文件夹。指定的路径应该相对于您的根文件夹。

'shared' => [
    'storage/logs',
    'storage/sessions',
    'storage/uploads',
    '.env',
],
登入後複製

可写目录

大多数共享目录还需要 Web 服务器能够写入它们。写入日志、会话或文件上传通常是任何应用程序执行的任务。您可以将这些内容添加到 remote.php 中的 permissions.files 数组中。

'permissions' => [
    'files' => [
        'storage/sessions',
        'storage/logs',
        'storage/uploads',
    ],
    // [...]
],
登入後複製

安装或更新依赖项

如果应用程序依赖于任何类型的依赖项,则需要安装或更新依赖项。该工具支持最流行的包管理器。如果您有默认设置,则无需进行任何配置。它将检测并安装或更新 Composer、Npm、Bower 和 Bundler 的依赖项。 依赖项 的默认策略设置为 Polyglot。这是该工具检测和安装不同包管理器依赖项的方法。

但是,假设您想要在 staging 上安装所有依赖项,并且该工具默认使用 --no-dev 标志。也许您想安装 PHPUnit 来运行测试,这是一个开发依赖项。在 strategies.php 中,您可以找到 composer 键,它告诉工具如何执行 Composer。然后,您可以在 config.php 中覆盖此设置:

use Rocketeer\Binaries\PackageManagers\Composer;

// [...]

'on' => [
    // [...]
    'connections' => [
        'staging' => [
            'strategies' => [
                'composer' => [
                    'install' => function (Composer $composer, $task) {
                        return $composer->install([], ['--no-interaction' => null, '--prefer-dist' => null]);
                    }
                ],
            ],
        ]
    ],
],
登入後複製

数据库迁移

当您拥有完整的版本时,在符号链接到当前版本之前,迁移数据库通常是您想要做的事情。无论您使用什么工具,您都可以让它在 deploy.before-symlink 之前运行。这个钩子不是普通的钩子,而是一个内部钩子。然后,您需要在 hooks.php 以外的其他地方注册它。您可以在 events.php 中执行此操作,如果该文件尚不存在,则可以创建该文件。

use Rocketeer\Facades\Rocketeer;

// Laravel
Rocketeer::addTaskListeners('deploy', 'before-symlink', function ($task) {
    $task->runForCurrentRelease('php artisan migrate');
});

// Symfony2
Rocketeer::addTaskListeners('deploy', 'before-symlink', function ($task) {
    $task->runForCurrentRelease('php app/console doctrine:migrations:migrate');
});

// Stand-alone Doctrine
Rocketeer::addTaskListeners('deploy', 'before-symlink', function ($task) {
    $task->runForCurrentRelease('doctrine migrations:migrate --no-interaction');
});
登入後複製

运行测试

在部署过程中运行测试是确保不会出现损坏的代码或测试的好方法。默认情况下,该工具使用 PHPUnit,您可以在安装或更新依赖项后挂钩测试运行器来运行。

'after' => [
    'setup'        => [],
    'deploy'       => [],
    'dependencies' => ['test'],
    'cleanup'      => [],
],
登入後複製

我们现在应该看到它在每个部署上执行 PHPUnit,并且如果测试失败,它将中止。确保您看到它的输出,否则在查找 PHPUnit 二进制文件或测试套件时可能会出现问题。

staging/0 |---- Test (Run the tests on the server and displays the output) fired by dependencies.after
staging/0 |------ Test/Phpunit (Run the tests with PHPUnit)
$ cd /var/www/my-deployable-app/releases/20160129220251$ /var/www/my-deployable-app/releases/20160129220251/vendor/bin/phpunit --stop-on-failure
[deploy@staging.mydeployableapp.com] (staging) PHPUnit 4.8.21 by Sebastian Bergmann and contributors.
[deploy@staging.mydeployableapp.com] (staging)
[deploy@staging.mydeployableapp.com] (staging) .
[deploy@staging.mydeployableapp.com] (staging) Time: 4.79 seconds, Memory: 6.00Mb
[deploy@staging.mydeployableapp.com] (staging) OK (1 test, 1 assertion)
[deploy@staging.mydeployableapp.com] (staging)staging/0 |=====> Tests passed successfully
登入後複製

前端构建工具

通常我们的应用程序不仅仅是后端,除非它们是 REST API。使用 Grunt、Gulp 或 Webpack 等工具运行前端构建工具是一项常见任务。使这成为我们部署过程的一部分没有什么比使用钩子来运行以下命令更奇特的了:

'after' => [
    'setup'        => [],
    'deploy'       => [],
    'dependencies' => ['gulp build'],
    'cleanup'      => [],
],
登入後複製

前端通常也依赖于依赖项,因此在安装或更新工具后运行工具。

提示与技巧

运行更新

如果您不想在部署时创建新版本,则可以选择运行更新。执行此操作时请务必小心,因为您将无法回滚到以前的版本,只能回滚到以前的版本。但这是一种使用最新更改更新应用程序的快速而简单的方法:

$ rocketeer update
登入後複製

本地任务

有时,在本地环境中运行任务可能会很好。假设您想要运行 PHPCS 检查或构建静态资产并将它们上传到服务器,从而消除服务器上某些二进制文件的需要。如果您创建任务类,则可以将受保护变量 $local 设置为 true

class MyTask extends Rocketeer\Abstracts\AbstractTask
{
    protected $local = true;

    // [...]
}
登入後複製

结论

部署过程是应用程序生命周期的重要组成部分。像 Rocketeer 这样的工具可以让您轻松地使这成为一件简单的事情。当将它用于 PHP 应用程序时尤其如此,因为它与 PHP 应用程序集成得非常好。

对于那些刚刚开始使用 PHP 或希望通过扩展来扩展您的知识、站点或应用程序的人,我们在 Envato Market 中提供了您可以学习的各种内容。

為 Rocketeer 編寫入門教學是一項艱鉅的任務。該工具非常靈活,以至於繪製停止位置並不容易。我希望我了解了使用此工具的可能性以及它如何使您和您的應用程式受益。如果您想深入了解,我建議您閱讀完整的文件。該工具的功能遠不止我在本文中所能介紹的內容。

以上是Rocketeer:部署 PHP 應用程式的終極工具的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!