Обновить проект на боевом сервере и ничего не сломать!
Надо обновлять проект на боевом сервере (или серверах)
Это надо делать часто.
Остановить какие-нибудь воркеры
Обновить код
Установить зависимости
Смигрировать БД
Запустить какие-нибудь воркеры
Пересобрать какие-нибудь картинки и стили
Все то время, пока выполняется обновление, сервер простаивает или отвечает 500 ошибками.
Если посадить человека выполнять 1000 раз одну и ту же последовательность команд, он ошибется. И не один раз. А если у вас несколько серверов? А если сотни?
Все уже давно автоматизировано, берите и пользуйтесь:)
Capistrano — это утилита для автоматизации серверных команд и деплоя, написанная на Ruby.
Подходит для деплоя проектов на любом языке.
По правильному, нам надо будет установить rvm, ruby 2.2, bundler и создать gemset для capistrano.
Но мы пойдем простым путем.
aptitude install ruby
Убедитесь, что установится ruby версии не ниже 1.9.3 !
gem install bundler
Убедитесь, что установится bundler версии не ниже 1.9.0
source 'https://rubygems.org'
ruby '~> 1.9.3'
#ruby-gemset=capistrano
gem 'capistrano', '~> 3.3.5'
gem 'capistrano-composer'
gem 'bundler', '~> 1.9.0'
gem 'rake', '~> 10.0.0'
bundle
Эта команда установит все зависимости из Gemfile. Да-да, с bundler целиком и полностью слизан Composer.
bundle exec cap install
Capfile
config
deploy
production.rb
development.rb
deploy.rb
Capfile
config
deploy
production.rb
development.rb
deploy.rb
Capfile
config
deploy
production.rb
development.rb
deploy.rb
Capistrano можно настроить таким образом, что оно будет выкладывать проекты на разные сервера, выполняя в процессе разные задачи.
Это бывает полезно, если у вас есть сервер разработки, сервер для тестирования и боевой сервер.
Все это можно разрулить при помощи capistrano stages.
Capfile
config
deploy
production.rb
development.rb
deploy.rb
set :deploy_config_path, 'application/config/deploy.rb'
set :stage_config_path, 'application/config/deploy'
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/composer'
Dir.glob('lib/capistrano/tasks/*.rake').each {
|r| import r
}
set :deploy_config_path, 'application/config/deploy.rb'
set :stage_config_path, 'application/config/deploy'
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/composer'
Dir.glob('lib/capistrano/tasks/*.rake').each {
|r| import r
}
set :deploy_config_path, 'application/config/deploy.rb'
set :stage_config_path, 'application/config/deploy'
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/composer'
Dir.glob('lib/capistrano/tasks/*.rake').each {
|r| import r
}
set :deploy_config_path, 'application/config/deploy.rb'
set :stage_config_path, 'application/config/deploy'
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/composer'
Dir.glob('lib/capistrano/tasks/*.rake').each {
|r| import r
}
set :deploy_config_path, 'application/config/deploy.rb'
set :stage_config_path, 'application/config/deploy'
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/composer'
Dir.glob('lib/capistrano/tasks/*.rake').each {
|r| import r
}
cap -T
Должен выпасть список доступных команд.
current -> releases/201505131954600
releases
201505131954600
repo (VCS-related data)
revisions.log
shared
current -> releases/201505131954600
releases
201505131954600
repo (VCS-related data)
revisions.log
shared
current -> releases/201505131954600
releases
201505131954600
repo (VCS-related data)
revisions.log
shared
current -> releases/201505131954600
releases
201505131954600
repo (VCS-related data)
revisions.log
shared
current -> releases/201505131954600
releases
201505131954600
repo (VCS-related data)
revisions.log
shared
current -> releases/201505131954600
releases
201505131954600
repo (VCS-related data)
revisions.log
shared
Capistrano создает символические ссылки на папки и файлы из shared в current.
Capistrano умеет деплоить сразу на несколько как равнозначных, так и разных серверов.
:web
. Сервер, где расположен веб-сервер (Apache, Nginx).:app
. Сервер, где расположено приложение (PHP). В мире PHP :web
и
:app
в 90% случаев одно и тоже.
:db
. Сервер БД.application/config/production.rb
server 'example.com', roles: %w(web app)
server 'mysql.example.com', roles: %w(db)
cap production deploy
deploy:starting
. Убедимся, что все хорошо.deploy:updating
. Создаем папку с релизом, копируем туда код.deploy:publishing
. Меняем симлинк current на новый релиз.deploy:finishing
. Подчищаем старые релизы, пишем в лог.После каждого действия выполняется хук deploy:*ed
(started, updated, published, finished).
before deploy:starting
. Событие перед началом шага.deploy:starting
. Шаг.after deploy:starting
. Событие после шага.Таким нехитрым образом можно научить Capistrano выполнять нужные нам действия в нужное время.
git pull
Ну да, capistrano из коробки не умеет почти ничего. И это хорошо:)
Зато ее можно научить чему угодно.
application/config/deploy.rb
namespace :workers do
task :stop do
on roles(:web) do execute '/var/www/stopall' end
end
end
cap production workers:stop
application/config/deploy.rb
after "deploy:starting", "workers:stop"
after "deploy:finished", :notify_finish do
run_locally do
execute "curl -X POST --data-urlencode 'payload={\"text\": \"Чот задеплоилось!\", \"channel\": \"#general\", \"username\": \"Capistrano\", \"icon_url\": \"http://alex-panshin.me/CapistranoLogo.png\"}' https://hooks.slack.com/services/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"
end
end
Выполнить что-то на всех серверах с ролью :web.
Выполнить что-то на локальной машине.
namespace :test do
task :phpunit do
on roles(:web) do
execute("cd #{release_path} && vendor/bin/phpunit -c phpunit.xml.dist")
end
end
end
Можно найти в документации к SSHKit.
Capistrano поддерживает чудовищное количество конфигурационных параметров, описывающих, какую ветку на какой сервер выкладывать.
Попробуем пробежаться по самым важным.
:application
. Название приложения.:repo_url
. URL вашего репозитория.:branch
. Ветка, откуда получать код.:scm
. Ваша VCS. По умолчанию, git.:deploy_to
. Путь, куда выкладывать проект:keep_releases
. Количество релизов, которые capistrano будет хранить.:ssh_options
. Параметры подключения по ssh.:composer_install_flags
. Параметры запуска Composer.Разумеется, это далеко не все. Подробности в официальной документации.
set :linked_files, fetch(:linked_files).push(
'application/config/amqp.php',
'application/config/apn.php'
)
set :linked_dirs, fetch(:linked_dirs).push(
'application/certificates',
'application/cache',
'application/backups'
)
У нас две большие проблемы:
В своем любимом терминале выполняем команды:
ssh-keygen -t rsa -C 'me@example.com'
ssh-add
application/config/production.rb
set :ssh_options {
key: %w(~/.ssh/id_rsa),
auth_methods: %w(publickey password)
}
Воспользуемся SSH Agent forwarding. Мы даем право серверу воспользоваться тем же ключом для авторизации на третьей стороне.
SSH это умеет из коробки, ничего настраивать не надо.
application/config/production.rb
set :ssh_options {
key: %w(~/.ssh/id_rsa),
forward_agent: true,
auth_methods: %w(publickey password)
}
Можно почитать в официальной документации.
ssh-add && cap %stage-name% %command:name%
%stage-name%
Укажите здесь имя стадии, где выполнить команду;%command:name%
Команда, которую нужно выполнить на сервере.cap production deploy
cap production deploy:rollback
cap production workers:stop
cap production db:dump