攻略 - Capistrano 部署 Laravel 项目

Capistrano

file
Capistrano 部署的原理和 Deployer 是一样的,@overtrue 大神写了一篇关于 delopyer 攻略,里面讲的操作原理,服务器端用户配置,允许访问 git 仓库和免密码登录的基本知识可以先了解下。

这篇文章主要详细介绍下 capistrano 的具体用法:

结构

Capistrano 部署成功后的代码文件结构是像这样的:

├── current -> /var/www/app_name/releases/20180120114500/
├── releases
│   |----- 20180080072500
│   |----- 20180090083000
│   |----- 20180100093500
│   |----- 20180110104000
│   |----- 20180120114500
├── repo
│   |----- <VCS related data>
├── revisions.log
└── shared
    |----- <linked_files and linked_dirs>

current, releases,shared 的含义和 deployer 的是一样的,版本是按时间排序的,repo 里包含了 VCS 的信息,比如 git 或者 svn,revisions.log 日志记载了每一次部署和 rollback 的详细信息。

流程

deploy:starting    - 开始部署 确认一切就绪
deploy:started     - started hook (自定义任务)
deploy:updating    - 更新服务器
deploy:updated     - updated hook
deploy:publishing  - 发布新的部署
deploy:published   - published hook
deploy:finishing   - 结束部署
deploy:finished    - finished hook

安装

推荐使用 RVM 去安装 ruby,最大的好处在于你可以安装不同的版本,而且能够在版本中随意切换。

\curl -sSL https://get.rvm.io | bash -s stable(安装 rvm)

安装完后,可以运行 source ~/.rvm/scripts/rvm 或者重开 shell window 激活 rvm。

rvm list known(查看版本)

rvm install 2.5(安装 ruby 2.5)

gem install capistrano(安装 capistrano,gem 类似于 composer)

配置

我一般会在项目的根目录下新建一个 deployment 文件夹,然后运行 cap install,这个命令会创建以下的配置文件:

├── Capfile
├── config
│   ├── deploy
│   │   ├── production.rb
│   │   └── staging.rb
│   └── deploy.rb
└── lib
    └── capistrano
            └── tasks

首先,看一下 Capfile,默认的配置即可,不需做太大修改。因为本文例子中 tasks 会定义在 deploy.rb 中,所以 lib 文件夹用不到,可以忽略。

# 加载 DSL 和设置 stages
require "capistrano/setup"

# 加载默认的部署任务
require "capistrano/deploy"

# 加载 SCM git 插件:
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git

# 加载自定义任务 `lib/capistrano/tasks`
# Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

其次,deploy.rb 中的基本配置如下,每个配置我做了简单的注释:

# 设置 capistrano 版本
lock "~> 3.11.0"

# 设置项目名称
set :application, 'app_name'
# 设置服务器上的部署路径
set :deploy_to, '/var/www/app_name'
# 设置 git 仓库的 url
set :repo_url, 'git@github.com:username/app_name.git'
# 设置部署版本保持的个数
set :keep_releases, 5
# 设置日志 level
set :log_level, :debug
# 设置样式,美化 Capistrano 在命令行的输出
set :format, :airbrussh
# 设置 ssh 使用的 key,免密码登录
set :ssh_options, {
    keys: %w(~/.ssh/id_rsa)
}

如果你需要在服务器上编译资源,可以设置环境变量,比如加载 nodejs 的路径:

set :default_env, {
    path: "/home/deployer/.nvm/versions/node/v10.9.0/bin:$PATH"
}

顺便提一下,无论在 MAC 还是服务器上,可以使用 NVM 安装 nodejs,这个和 ruby 的 RVM 是一样的,让你安装不同的 nodejs 和 npm 的版本,而且很容易切换。

下面就是比较重要的 shared 的文件和文件夹,用来存储版本之间共享的文件:

set :linked_files, %w{.env}

set :linked_dirs, %w{
    vendor
    storage
    storage/app/public
    storage/framework/cache
    storage/framework/sessions
    storage/framework/testing
    storage/framework/views
    storage/logs
}

然后,定义一些常用的任务,比如:

namespace :app do
    task :up do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path do
                execute :php, :artisan, "up"
            end
        end
    end

    task :down do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path do
                execute :php, :artisan, "down"
            end
        end
    end

    ......
end

定义这些任务后,就可以本地运行 php artisan 命令,例如 cap staging app:down 就可以把服务器上的网站设置为维护模式。再以缓存为例子,在 namespace cache 下可以定义以下任务:

namespace :cache do
    task :clear do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path do
                execute :php, :artisan, "cache:clear"
                execute :php, :artisan, "view:clear"
                execute :php, :artisan, "route:clear"
                execute :php, :artisan, "config:clear"
            end
        end
    end

    task :route do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path do
                execute :php, :artisan, "route:cache"
            end
        end
    end

    task :config do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path do
                execute :php, :artisan, "config:cache"
            end
        end
    end

    task :refresh do
        invoke('cache:clear')
        invoke('cache:route')
        invoke('cache:config')
    end
end

所有的 php artisan 命令你都可以归类写成 task,放在 lib/capistrano/tasks 下,我们就简单放在 deploy.rb 里了。

接着 deploy 的配置:

namespace :deploy do
    desc "Run Composer Install"
    task :composer_install do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path do
                execute :composer, "install --prefer-dist --no-dev --optimize-autoloader"
            end
        end
    end

    desc "Run Migration"
    task :migrate do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path do
                execute :php, "artisan migrate --no-interaction --force"
            end
        end
    end

    desc "Run NPM Scripts"
    task :npm_scripts do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path do
                execute :npm, "install"
                execute :npm, "run production"
            end
        end
    end

    desc "Restart PHP FPM"
    task :restart_php_fpm do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path do
                execute :sudo, :service, "php7.2-fpm restart"
            end
        end
    end

    after :updated, "deploy:composer_install"
    after :updated, "deploy:migrate"
    after :updated, "deploy:npm_scripts"
    after :published, "deploy:restart_php_fpm"
end

这里需要注意的是,部署不需要重启 apache 或者 nginx,不过需要重启 php-fpm,这就需要给服务器用户 deployer 重启 php-fpm 的权限,安全起见,请仅给予重启 php-fpm 的权限
sudo visudo
deployer ALL=(ALL:ALL) NOPASSWD:/usr/sbin/service php7.2-fpm restart

最后,deploy/staging.rb 中的配置如下:

set :stage, :staging

set :branch, 'develop'

server '{server_ip_address}', user: 'deployer', roles: %w{app}

set :app_env, 'staging'

这样每次部署到测试服务器时,只需要本地运行 cap staging deploy 就可以,production 的配置类似。部署是需要一段时间的,不过只有最终成功的时候,服务器上才会更新 symlink,指向最新的版本,所以基本上是没有 downtime 的。

本作品采用《CC 协议》,转载必须注明作者和本文链接
jltxwesley
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!