Развертывание WordPress с помощью Mina

Поскольку система WordPress является PHP-приложением, она обычно развертывается при помощи достаточно старого метода – загрузки файлов по FTP.

Конечно, в природе существуют некоторые инструменты для развертывания, однако зачастую они требуют знаний в сфере Ruby. К примеру, один из достаточно популярных, мощных инструментов – Capistrano, — поставляется вместе с многочисленными связанными с Ruby/Rails возможностями. Как мне кажется, обычному PHP-разработчику, не знакомому с Ruby, будет довольно сложно установить Capistrano.

Так какие же варианты у нас, как у разработчиков WordPress, имеются?

В этом руководстве я познакомлю вас с Mina – небольшим, легким инструментом, который позволяет добиться быстрого развертывания и автоматизации серверных задач.

Почему мы нуждаемся в автоматическом развертывании?

Автоматическое развертывание позволяет нам сэкономить время, которое обычно уходит на выполнение однотипных задач каждый раз, когда мы начинаем развертывать свой собственный проект на WordPress. Также оно помогает минимизировать время простоя в процессе развертывания и устранить человеческие ошибки: нехватку важных файлов, загрузку неправильных файлов и т.д.

К автоматическому процессу могут быть привлечены сразу несколько разработчиков одной команды, что позволяет создать уникальный метод развертывания. Одна из компаний (не будем называть ее имя) практически обанкротилась из-за отсутствия продуманного процесса развертывания. Автоматизированный метод развертывания обычно связан с системой управления исходным кодом: Git, SVN, Mercurial и т.д.

В пределах этого руководства мы будем использовать Git. Если у вас уже есть Git репозиторий, вы можете использовать его; в противном случае создайте его бесплатно с помощью BitBucket или GitLab. Эти службы позволяют создавать приватные Git репозитории.

Перед тем, как пойти дальше, давайте убедимся в том, что мы имеем следующее:

  • SSH соединение
  • Git репозиторий
  • Oermission для редактирования и изменения конфигурации веб-сервера

Примечание: я предполагаю, что у вас запущен WordPress на Apache с установленным модулем Apache PHP. Если вы используете PHP с FPM или CGI, то в таком случае вам придется самостоятельно проводить параллели с теми примерами, которые мы приводим.

Развертывание с помощью хуков Git

Общая идея заключается в том, что когда мы запускаем сервер, то Git вызывает URL, связанный с PHP-скриптом, который выполняет развертывание путем получения (или слияния) самого свежего кода из репозитория.

Такой способ прекрасно работает, однако он содержит в себе одну дыру: мы открываем секретную дверь на сервере. Если кто-либо узнает URL, то он сможет вручную инициировать развертывание. Другая опасность такого подхода – мы должны создать функции для очистки, отката, блокировки (чтобы убедиться в том, что запущен только один процесс развертывания) и т.д.

Кодирование этих функций аналогично повторному изобретению колеса. Так почему бы нам не воспользоваться уже существующими инструментами?

Что представляет собой Mina?

Mina – эффективный и быстрый инструмент развертывания; вы будете удивлены, как быстро выполняется процесс развертывания с помощью Mina. Веб-сайт Mina говорит следующее:

«Действительно быстрый инструмент развертывания и серверной автоматизации. Чертовски быстрый».

Проще говоря, вот как работает Mina: вместо того, чтобы входить на сервер и вбивать последовательность команд для развертывания, Mina генерирует shell-скрипт, который является набором данных команд.

  1. Создаем новую директорию.
  2. Помещаем свежий код в данную директорию.
  3. Делаем символьные ссылки к общим ресурсам.
  4. Переносим публичную директорию в нашу новую директорию.
  5. Очищаем старые данные.

Mina загружает shell-скрипт на сервер и выполняет его. Процесс генерации скрипта, представленный выше, выполняется на вашей локальной машине.

Все задачи Mina представляют собой обычную последовательность shell-команд. Поскольку это всего лишь shell-команды, у вас нет доступа к фантастическому хелперу Ruby, который присутствует в Capistrano или Vlad.

Также можно рассматривать Mina следующим образом: Mina представляет ваши shell-команды, которые требуются вам для запуска на удаленной машине, в виде блоков кода (которые называются задачами).

Шаг 1. Готовим подходящую структуру сервера для Mina.

Mina требует для своей работы определенной структуры директорий для нового сайта. Вам нужно будет изменить директорию public для вашего веб-сервера. Предположим, что текущая структура директорий сервера является следующей:

/var/www/yourdomain.com/     # The public directory where your WordPress sits
|-  index.php
|-  wp-admin
|-  wp-content
|-  wp-includes
|-  wp-login.php
|-  wp-activate.php
|-  ….

yourdomain.com указывает на /var/www/yourdomain.com/, и файл index.php, который находится внутри директории, выполняется и отвечает на ваш запрос. Для Mina вам нужно будет немного изменить структуру каталогов.

Mina ожидает увидеть следующую структуру:

/var/www/yourdomain.com/     # The deploy_to path
|-  releases/              # Holds releases, one subdir per release
|   |- 1/                       # Each of WordPress deployment sit here
|   |- 2/                       # Each of WordPress deployment sit here
|   |- 3/                       # Each of WordPress deployment sit here
|   |- ...
|-  shared/                # Holds files shared between releases: such as log file, config,…
|   |- logs/                 # Log files are usually stored here
|   - ...
|-  current/               # A symlink to the current release in releases, this will be new public folder

Mina добавляет три директории:

  1. releases: каждое развертывание будет сохраняться в отдельных директориях внутри этой папки, что позволит вам обслуживать версию 1, версию 2, версию 3 и т.д.
  2. shared: содержит общие файлы/папки, которые совместно используются в многочисленных развертываниях. Как пример: wp-content/uploads. В каждом развертывании мы будем иметь новую папку wp-content/uploads, которая отличается от предыдущей папки wp-content/uploads. Таким образом, мы будем использовать общую директорию: shared/wp-content/uploads. Соответственно, /var/www/yourdomain.com/releases/7/wp-contents/uploads – это символьная ссылка, указывающая на /var/www/yourdomain.com/shared/wp-content/uploads.
  3. current: указывает на текущий релиз. Пример: /var/www/yourdomain.com/current ссылается на /var/www/yourdomain.com/releases/7.

Yourdomain.com теперь должен указывать на /var/www/yourdomain.com/current вместо /var/www/yourdomain.com. Веб-сервер будет запускать файл /var/www/yourdomain.com/current/index.php, когда вы посетите http://yourdomain.com. Нам нужно заново сконфигурировать веб-сервер (Apache, Nginx) для привязки docroot (или public directory) к директории current.

Изменяем DocumentRoot для Apache

Открываем /etc/httpd/conf/httpd.conf, ищем в нем строку DocumentRoot и меняем ее на:

DocumentRoot /var/www/yourdomain.com/current

Изменяем Document Root для Nginx

Редактируем /etc/nginx/nginx.conf и обновляем определение root:

server {
server_name log.axcoto.com www.log.axcoto.com;
root /srv/http/domain/log.axcoto.com/current/;
# …
}

Шаг 2. Установка Mina

Mina основана на Ruby, поэтому вам понадобится установить Ruby. Установка достаточно простая. Если вы работаете с OS X или Linux, то в таком случае у вас, возможно, уже будет установлен Ruby; иначе вы можете следовать разным руководствам по установке Ruby.

Для установки Ruby запустите следующее:

$ gem install mina

Убедитесь в том, что Ruby запущен должным образом:

$ mina -V

Вы должны увидеть что-то подобное:

Mina, version v0.3.0

Развертывание WordPress с помощью Mina

Один из аспектов, который делает PHP-приложений менее защищенными, заключается в установке некорректных прав доступа.

Возьмем для примера WordPress: допустим, я хочу загрузить плагин или тему, чтобы попробовать их. Соответственно, я загружаю их в консоли WordPress. Если я или один из администраторов сайта потеряем пароль от своего аккаунта, а кто-то другой получит его, то в таком случае этот человек может загрузить PHP-файл и запустить его в виде плагина, взломав не только сам сайт, но и весь сервер.

Эти люди могут прочитать файлы в /etc, изучить серверную конфигурацию, а затем запустить shell-команды через PHP.

Я думаю, мы должны рассматривать экземпляр WordPress как сборку, открытую только для чтения. Установку плагинов и тем мы можем проводить путем локального добавления файлов и повторного развертывания с помощью Mina. Развертывание с помощью Mina – недорогой и быстрый способ. На моем сервере 512MB RAM DigitalOcean такое развертывание занимает менее 30 секунд.

Для загруженного пользователями контента (изображений, аудио и т.д.) мы будем использовать символьные ссылки, ведущие за пределы директории с исходным кодом. В идеале мы можем сконфигурировать сервер так, чтобы предотвратить выполнение любого PHP-скрипта внутри папки с загруженным пользователем контентом, однако это выходит за рамки нашего руководства.

На данный момент мы попытаемся использовать Mina для быстрого развертывания, а также добавления темы или плагина, причем сделаем это локально, т.е. мы сможем избежать установки прав доступа для записи в данные директории.

Шаг 1. Устанавливаем Mina в WordPress

Как было сказано в самом начале нашего руководства, у вас должен иметься Git репозиторий для вашего WP-сайта. Нам понадобится следующее:

  1. Ваш проект WordPress должен находиться в ~/Site/wordpress.
  2. Ваш git репозиторий WordPress должен быть следующим: git@bitbucket.org/yourname/wordpress.
  3. Вы можете получить доступ к вашему серверу через ssh с аккаунтом yourname на yourdomain.com.

Если ваш исходный код WordPress не содержится в Git репозитории, давайте исправим это прямо сейчас; иначе перейдите к следующему шагу.

$ cd ~/Site/wordpress
$ git init
$ git remote add origin git@bitbucket.org:kureikain/wordpress.git
$ git add .
$ git push origin master

Запустите команду ниже, чтобы начать настройку Mina для вашего проекта.

$ mina init

В итоге мы получим папку config с единственным файлом deploy.rb внутри нее.

$  ls
config               wp-blog-header.php   wp-load.php
index.php            wp-comments-post.php wp-login.php
latest.tar.gz        wp-config-sample.php wp-mail.php
license.txt          wp-content           wp-settings.php
readme.html          wp-cron.php          wp-signup.php
wp-activate.php      wp-includes          wp-trackback.php
wp-admin             wp-links-opml.php    xmlrpc.php
 
$  ls config
deploy.rb

Шаг 2. Настраиваем config/deploy.rb

Теперь давайте откроем config/deploy.rb и определим некоторую конфигурацию:

Файл deploy.rb содержит в себе конфигурацию развертывания, а также набор задач Mina. Каждая задача заключена в блок task :taskname. Внутри каждой задачи мы можем вызывать другую задачу с помощью invoke. Чтобы запустить команду на сервере, достаточно определить ее в queue.

К примеру, задача может иметь следующий вид:

task :down do
  invoke :maintenance_on
  invoke :restart
  queue 'rm -rf /tmp/cache'
end

Учитывая это, давайте перейдем к редактированию файла deploy.rb.

Удаляем неиспользуемые строки

Закомментируйте следующие строки, поскольку мы не будем использовать их:

#require 'mina/bundler'
#require 'mina/rails'

Настраиваем определение сервера

Стандартный код имеет следующий вид:

set :user, 'username'
set :domain, 'foobar.com'
set :deploy_to, '/var/www/foobar.com'
set :repository, 'git://...'
set :branch, 'master'
  1. domain – это доменное имя вашего WordPress-сайта
  2. deploy_to – где вы хотите расположить ваш проект WordPress
  3. repository – адрес вашего Git-репозитория
  4. branch – ветвь развертывания. Git поддерживает много ветвей, и многие люди обычно используют ветвь deploy для развертывания.

Давайте обновим нашу конфигурацию сервера:

set :domain, 'yourdomain.com'
set :deploy_to, '/var/www/yourdomain.com'
set :repository, 'https://kureikain@bitbucket.org/kureikain/wordpress.git'
set :branch, 'master'
set :user, 'your_username'    # Username in the server to SSH to.

Убедитесь в том, что вы у вас есть доступ к repository на вашей удаленной машине.

Затем мы обработаем папку wp-content/uploads. Эта папка содержит загруженный пользователями контент. Каждый раз при развертывании эта папка будет отличаться от той, которую мы в настоящее время используем, поскольку недавно развернутый код находится в разных папках внутри releases.

Если мы оставим эту новую папку, то мы потеряем весь старый контент. Также мы должны использовать символьную ссылку, чтобы указать на старый контент, содержащийся в другом месте. После развертывания мы обновим ссылку, чтобы она указывала на корректный контент.

Ищем следующее:

set :shared_paths, ['config/database.yml', 'log'] 

И меняем на:

set :shared_paths, [ 'wp-content/uploads'] 

shared_paths – это набор общих ресурсов (файлов/папок) для разных версий. Он может отличаться в пределах того или иного релиза. Как и файлы журнала, контент, загруженный пользователями, должен находиться в shared_paths. Если этого не сделать, мы можем потерять данные с выходом каждого нового релиза.

К примеру, когда пользователь загружает файл, WordPress сохраняет его по адресу /var/www/yourdomain.com/current/wp-content/upload/2014/01/29/picture.png. Однако /var/www/yourdomain.com/current – это символьная ссылка, указывающая на /var/www/yourdomain.com/releases/4/, т.е. на наш текущий релиз. Таким образом, актуальный файл будет располагаться по адресу: /var/www/yourdomain.com/releases/4/wp-content/upload/2014/01/29/picture.png.

Теперь, если вы выпустите новый релиз, current будет указывать на /var/www/yourdomain.com/releases/5. Файл /var/www/yourdomain.com/current/wp-content/upload/2014/01/29/picture.png больше не располагается по данному пути, поскольку /var/www/yourdomain.com/releases/5/wp-content/uploads – новая папка, в которой нет контента.

Мы должны поместить ее в shared_paths, и Mina создаст символьную ссылку, связывающую /www/yourdomain.com/releases/5/wp-content/uploads с www/yourdomain.com/shared/wp-content/uploads.

Настраиваем нашу задачу Setup

Это задача, которую мы будем запускать в самом начале для подготовки нашей серверной среды. Выглядит она в стандартном виде следующим образом:

task :setup => :environment do
  queue! %[mkdir -p "#{deploy_to}/shared/log"]
  queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"]
 
  queue! %[mkdir -p "#{deploy_to}/shared/config"]
  queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"]
 
  queue! %[touch "#{deploy_to}/shared/config/database.yml"]
  queue  %[echo "-----> Be sure to edit 'shared/config/database.yml'."]
end

Давайте изменим ее на:

task :setup => :environment do
  queue! %[mkdir -p "#{deploy_to}/shared/wp-content/uploads"]
end

Наша задача setup просто создает папку wp-content/uploads.

Настраиваем задачу Deploy

Стандартная задача Deploy выглядит следующим образом:

task :deploy => :environment do
  deploy do
    # Put things that will set up an empty directory into a fully set-up
    # instance of your project.
    invoke :'git:clone'
    invoke :'deploy:link_shared_paths'
    invoke :'bundle:install'
    invoke :'rails:db_migrate'
    invoke :'rails:assets_precompile'
 
    to :launch do
      queue "touch #{deploy_to}/tmp/restart.txt"
    end
  end
end

Нам не нужно все то, что имеет отношение к Rails. Кроме того, поскольку развертывание WordPress не требует рестарта веб-сервера или PHP-процесса, нам надо лишь вызвать задачи git:clone и deploy:link_shared_paths.

Давайте изменим стандартную задачу на:

task :deploy => :environment do
  deploy do
    # Put things that will set up an empty directory into a fully set-up
    # instance of your project.
    invoke :'git:clone'
    invoke :'deploy:link_shared_paths'
  end
end

Настраиваем задачу Rollback

Поскольку Mina не предлагает никакого официального метода для выполнения отката, мы создадим задачу для нашего собственного процесса отката. Задача отката будет удалять текущий релиз и перенаправлять существующую символьную ссылку на предыдущий релиз. Добавьте эту задачу в конец файла deploy.rb:

desc "Rollback to previous verison."
task :rollback => :environment do
  queue %[echo "----> Start to rollback"]
  queue %[if [ $(ls #{deploy_to}/releases | wc -l) -gt 1 ]; then echo "---->Relink to previos release" && unlink #{deploy_to}/current && ln -s #{deploy_to}/releases/"$(ls #{deploy_to}/releases | tail -2 | head -1)" #{deploy_to}/current && echo "Remove old releases" && rm -rf #{deploy_to}/releases/"$(ls #{deploy_to}/releases | tail -1)" && echo "$(ls #{deploy_to}/releases | tail -1)" > #{deploy_to}/last_version && echo "Done. Rollback to v$(cat #{deploy_to}/last_version)" ; else echo "No more release to rollback" ; fi]
end

Код выше выглядит достаточно сложным, однако в действительно он представляет собой короткую версию следующего кода. Я разбил его по строкам и привел аннотацию к каждой команде:

# Проверяем, есть ли у нас более 1 релиза
if [ $(ls /var/www/yourdomain.com/releases | wc -l) -gt 1 ]
then
  echo "---->Relink to previos release"
  # Удаляем текущую символьную ссылку
  unlink /var/www/yourdomain.com/current
  # Связываемся с предыдущим релизом
  ln -s /var/www/yourdomain.com/releases/"$(ls /var/www/yourdomain.com/releases | tail -2 | head -1)" /var/www/yourdomain.com/current
  echo "Remove old releases"
  # Удаляем последний релиз, который мы уже откатили
  rm -rf /var/www/yourdomain.com/releases/"$(ls /var/www/yourdomain.com/releases | tail -1)"
  # Заносим текущую версию в файл last_version
  echo "$(ls /var/www/yourdomain.com/releases | tail -1)" > /var/www/yourdomain.com/last_version
  # Выводим некоторую информацию пользователям
  echo "Done. Rollback to v$(cat /var/www/yourdomain.com/last_version)"
else
  # Если у нас нет более 1 релиза, то мы не можем сделать откат
  echo "No more release to rollback"
fi

Итак, мы настроили сервер, отредактировали задачи setup, deploy и rollback. Теперь давайте перейдем к использованию Mina.

Развертывание с помощью Mina

В этой части я покажу вам, как запустить Mina для настройки сервера, развертывания сервера и выполнения отката. Mina — это утилита с интерфейсом командной строки. У вас должен быть доступ к терминалу. Каждая задача Mina будет вызываться из терминала.

Шаг 1. Подготовка

Мы будем делать этот шаг только один раз, когда мы подготавливаем развертывание на сервере. Соединяемся через SSH с сервером и создаем директорию deploy_to. В нашем случае она содержится по адресу: /var/www/yourdomain.com.

$ ssh your_name@yourdomain.com
# on your remote machine (after you connected via SSH), run this
$ sudo mkdir -p /var/www/yourdomain.com
$ sudo chown -R your_name /var/www/yourdomain.com

При запуске команды chown мы изменим владельца /var/www/yourdomain.com на your_name. Таким образом, сервер не сможет ничего записать в эту директорию. Наш WordPress-сайт станет более защищенным. Затем на локальной машине запускаем mina setup. Мы увидим следующее:

$ mina setup
-----> Setting up /var/www/yourdomain.com
 
       total 16
       drwxr-xr-x 4 kurei root  4096 Jan 27 22:51 .
       drwxr-xr-x 3 root  root  4096 Jan 27 00:16 ..
       drwxr-xr-x 2 kurei users 4096 Jan 27 22:51 releases
       drwxr-xr-x 2 kurei users 4096 Jan 27 22:51 shared
 
-----> Done.
       Elapsed time: 1.00 seconds

Если вы хотите проверить, что именно создала Mina на вашем сервере, выполните следующий код:

$ cd /var/www/yourdomain.com
$  ls
releases  shared
$ ls shared/wp-content
uploads

На данном этапе у нас есть почти все, что нам нужно. Помните, что директория загрузок хранит в себе контент, загружаемый пользователями. Веб-сервер должен быть в состоянии вести запись в эту папку. Мы должны определить, какой пользователь вашего Apache/Nginx (или PHP FPM Process в зависимости от настроек вашего сервера) в данный момент используется, после чего изменить владельца папки загрузок на него, чтобы разрешить серверу запись в эту папку. Если вы откроете ваш конфигурационный файл Apache или Nginx, то вы сможете найти пользователя:

# For Apache, open /etc/httpd/conf/httpd.conf
 User www Group www

# For Nginx, open /etc/nginx/nginx.conf

user http http; worker_processes 2;

Предположим, что Apache запущен для пользователя www:

ssh your_username@yourdomain.com sudo chown -R www /var/www/yourdomain.com/wp-content/uploads

Шаг 2. Развертывание

Всякий раз, когда мы хотим развернуть код, нам понадобится использовать следующую задачу.

Вот как выглядит сам процесс:

  • Обновляем код
  • Фиксируем изменения
  • Передаем код на Git сервер

Давайте проведем развертывание.

$ mina deploy

Через несколько секунд оно завершится. Вот пример вывода результатов развертывания:

$ mina deploy
-----> Creating a temporary build path
-----> Fetching new git commits
-----> Using git branch 'master'
       Cloning into '.'...
       done.
-----> Using this git commit
 
       kureikain (347d9b3):
       > Update new config/deploy
 
-----> Symlinking shared paths
-----> Build finished
-----> Moving build to releases/2
-----> Updating the current symlink
-----> Launching
-----> Done. Deployed v2
       Elapsed time: 1.00 seconds

Шаг 3. Откат

Если релиз содержит критические ошибки или мы просто хотим откатить код к предыдущей версии по каким-либо причинам, то в таком случае можно выполнить следующий код:

$ mina rollback

Вывод будет иметь следующий вид:

----> Start to rollback
----> Relink to previous release
Remove old releases
Done. Rollback to v2
Connection to axcoto.com closed.
       Elapsed time: 0.00 seconds

Далее

В следующей части мы посмотрим на WP-CLI. В частности, мы изучим, как использовать WP-CLI, а также как выполнять общие задачи администрирования, такие как обновление WordPress, установка тем, плагинов и т.д. через WP-CLI с помощью задач Mina. Мы также посмотрим на то, как сделать нашу сборку WordPress более безопасной.

Источник: code.tutsplus.com/articles

Блог про WordPress
Комментарии: 3
  1. AAMix

    Чем больше я узнаю нового, чем больше убеждаюсь, что я ничего толком и не знаю ;)
    Возьмем наш сайт на заметку, так как темы WordPress и их редактирование в последнее время мне интересны. А здесь есть что почитать.
    С уважением, александр Афанасьев.

  2. Александр

    Немного не понял смысла всего этого.

    1. Дмитрий (автор)

      Деплоймент (deployment, развёртывание) – установка (или обновление) программного обеспечения (в нашем случае – веб-сайта) на целевом оборудовании. Говоря просто – процесс, в результате которого сайт, который работал на машине разработчика, начал работать на специально под него выделенном оборудовании и программном обеспечении.

Добавить комментарий

Получать новые комментарии по электронной почте.