攻略 - Capistrano 部署 Laravel 项目
Capistrano
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 协议》,转载必须注明作者和本文链接