Как настроить деплоймент сайта на WordPress с помощью Git

Веб ,

Деплоймент сайта на WordPress при помощи GitЧто такое деплоймент сайта? Это слово происходит от английского deployment и буквально означает развёртывание, ввод в действие. Если говорить о веб-разработке, это означает перенос сайта из локальной среды разработки на веб-сервер вашего хостинг-провайдера, к которому по прямой ссылке, например http://ixrevo.me, имеют доступ ваши клиенты, то есть посетители сайта. В этой статье я опишу способ деплоймента, на примере сайта под управлением WordPress, с помощью системы контроля версий Git. Этот способ подойдёт для небольшого веб-приложения, сайта или блога.

Зачем вообще нужна система деплоймента?

Ведь можно просто копировать файлы по FTP с локальной машины на сервер или вообще использовать текстовый редактор, который имеет функцию редактирования файлов по FTP прямо на сервере.

Редактирование по FTP

Для этих целей подходят редакторы: Coda, Dreamweaver или бесплатный TextWrangler. Другой вариант — смонтировать папку с сайтом, расположенную на удалённом сервере, как локальный диск и редактировать файлы в любом текстовом редакторе на ваш вкус. Это можно сделать используя, например, функцию FTP клиента Transmit Disks. Суть процесса при этом не меняется — вы редактируете файлы напрямую на сервере.

Такой подход имеет два неоспоримых преимущества: он не требует сложных настроек и вы получаете результат настолько быстро, насколько это возможно. Но недостатков такой способ работы имеет больше:

  • Это опасно, потому что люди часто ошибаются, а результат ошибки сразу виден конечному пользователю.
  • При таком подходе невозможно тестирование.
  • Нет истории изменений (когда, что, кем и зачем).
  • Изменения невозможно отменить, после того как они были применены.
  • Можно удалить изменения, которые были внесены другими членами команды.
  • Работа в команде над более-менее крупным проектом практически невозможна.

Редактирование локально и копирование файлов на сервер по FTP

Думаю, эта самый распространённый способ, используемый при разработке сайтов, особенно в домашних условиях. Он имеет те же самые недостатки, как и предыдущий метод, за исключением возможности сначала протестировать перед выкладкой внесённые изменения. Затереть же чужие изменения так ещё проще, потому что обычно забываешь, что именно ты поменял, и копируешь все файлы разом.

Система контроля версий

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

Фрагмент скриншота системы контроля версий GitHub отображающий изменения
Пример отображения изменений в системе контроля версий

Существует несколько систем контроля версий. Самая известная и распространённая  — это Git, также есть Subversion, которую, кстати, использует проект WordPress.Org, и чуть менее известная, но тоже широко используемая Mercurial. Сам я использую Git и всем советую.

Настройка деплоймента сайта

Существует огромное количество вариантов деплоймента сайтов, начиная от простого копирования папки с файлами сайта с локального компьютера на сервер при помощи FTP клиента, которое мы рассмотрели выше, и заканчивая сложными распределёнными системами для высоконагруженных систем. Если вы не собираетесь деплоить какой-нибудь Twitter, а просто занимаетесь веб-разработкой, например, сайтов на WordPress, хотите свой код держать в системе контроля версий и иметь простой способ выкатывать апдейты на веб-сервер с вашим сайтом, то этот способ вам скорее всего подойдёт. Единственное что от вас потребуется — это обладать начальными навыками работы с Git, знать базовые операции в командной строке и приблизительно знать что такое SSH.

Схема деплоймента сайта
Применение изменений к сайту, используя деплоймент через Git репозиторий

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

  1. Вы вносите изменения в своей локальной среде разработки и тестируете их локально.
  2. Затем, когда вы довольны результатом, вы коммитите (сохраняете) изменения в локальный репозиторий системы контроля версий.
  3. И пушите эти изменения в репозиторий на вашем веб-сервере.
  4. На сервере отрабатывает post-recieve хук и изменения из репозитория распаковываются в папку с сайтом — деплоймент произошёл, новая версия сайта доступна для ваших пользователей.

Настройка удалённого сервера

Чтобы этот способ деплоймента работал, необходимо чтобы на веб-сервере был установлен Git и у вас был к нему доступ по ssh. У моего хостинг-провайдера они были установлены и настроены сразу из коробки, но если на вашем хостинге этого нет, то вы можете написать в службу поддержки и попросить установить вам Git и дать доступ подключаться к серверу по ssh.

Итак, приступим к настройке.

  1. Заходим по ssh на сервер, где располагается сайт, для чего на Mac’е открываем приложение Терминал и выполняем:

    ssh username@example.com

    Имя пользователя username и пароль, который потребуется ввести, надо узнать у хостинг-провайдера.

  2. Переходим в директорию сайта и создаём там папку для git-репозитория:

    cd ~/example.com
    mkdir repo.git

    Я называю эту папку просто repo.git, чтобы получилось более короткое название, а поскольку она лежит уже внутри папки сайта, то её имя не будет конфликтовать с репозиториями других сайтов, которые вы захотите деплоить на этом сервере.

    (!) Главное ни в коем случае не размещайте папку репозитория внутри папки доступной извне. Она обычно называется public_html или htdocs.

  3. Далее переходим в папку репозитория:

    cd example.com/repo.git

    и инициализируем пустой репозиторий:

    git init --bare

    Должно отобразиться сообщение похожее на:

    Initialized empty Git repository in /home/username/example.com/repo.git/

На этом мы пока закончим с нашим сервером и вернёмся на локальный компьютер.

Настройка локального компьютера

Чтобы настроить локальный компьютер, необходимо скопировать папку с сайтом. Обычно это ~/example.com/public_html или ~/example.com/htdocs.

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

Проще всего это сделать при помощи FTP клиента, например, можно использовать бесплатный Cyberduck для Mac OS X или FileZilla для Windows. Сам я использую Transmit, но он платный.

После того как мы скопировали папку с сайтом (предположим, что мы его скопировали в директорию /Users/username/Sites/), необходимо сделать пару манипуляций, чтобы сайт был готов к деплойменту.

Файл конфигурации WordPress

Локально установленный WordPress работает с базой данных, которая находится на локальном компьютере. Как сделать так, чтобы после деплоя на веб-сервер сайт продолжал работать, ведь настройки DB_NAME, DB_USER, DB_PASSWORD и, возможно, DB_HOST на сервере отличаются от локальных?

  1. Для решения этой проблемы надо в файле конфигурации wp-config.php найти строки, где определяются настройки подключения к базе данных, и обернуть их в такой if:

    
    if ( file_exists( dirname( __FILE__ ) . '/wp-config-local.php' ) ) {
    	include( dirname( __FILE__ ) . '/wp-config-local.php' );
    }
    else {
    	// Настройки базы данных на веб-сервере
    	define('DB_NAME', 'Имя_Базы_Данных');
    	define('DB_USER', 'Имя_Пользователя_Локальной_Базы_Данных');
    	define('DB_PASSWORD', 'Пароль_Локальной_Базы_Данных');
    	define('DB_HOST', 'Хост_Локальной_Базы_Данных');
    
    	// Выключаем debug на веб-сервере
    	define('WP_DEBUG', false);
    }
    

    Заодно в этот if можно внести настройку WP_DEBUG.

  2. После чего на локальной машине в корень сайта (туда же, где лежит обычный wp-config.php) добавить файл wp-config-local.php, и в этом файле указать локальные настройки базы данных:

    <?php
    // Локальные настройки WordPress
    
    // Локальная база данных
    define('DB_NAME', 'Имя_Локальной_Базы_Данных');
    define('DB_USER', 'Имя_Пользователя_Локальной_Базы_Данных');
    define('DB_PASSWORD', 'Пароль_Локальной_Базы_Данных');
    define('DB_HOST', 'Хост_Локальной_Базы_Данных');
    
    // Включаем debug для локальной среды разработки
    define('WP_DEBUG', true);
    define('JETPACK_DEV_DEBUG', true);
    define('CONCATENATE_SCRIPTS', false);
    
  3. Не забудьте проверить, что в .gitignore (об этом файле речь пойдёт чуть ниже) добавлен файл wp-config-local.php, потому что, если он попадёт на веб-сервер, WordPress не сможет соединиться с базой данных и сломается.

В результате всех этих манипуляций на локальной машине WordPress будет брать настройки из файла wp-config-local.php, а на веб-сервере, где этого файла нет, настройки будут браться из секции else файла wp-config.php.

Добавляем файлы в Git

  1. Теперь всё готово для того, чтобы добавить файлы нашего сайта в систему контроля версий Git. Для этого открываем Terminal и переходим в директорию, куда мы скопировали файлы сайта, и инициализируем Git репозиторий:

    cd ~/Sites/example.com
    git init

    Видим сообщение, что всё идёт, как мы задумали:

    Initialized empty Git repository in /Users/uzername/Sites/example.com/.git/
  2. Добавляем в корень сайта файл .gitignore, в котором мы исключим те файлы и директории, которые не хотим отслеживать в системе контроля версий. Например, файлы ядра WordPress, файлы сторонних плагинов и всё в таком духе. Можно использовать мою заготовку .gitignore.
  3. После чего добавляем файлы сайта и коммитим их в репозиторий:

    git add .
    git commit -m "Initial commit."
  4. Подключаем к локальному репозиторию удалённый, который находится на нашем веб-сервере:

    git remote add web ssh://username@example.com/home/username/example-com.git

    Проверяем, что он подключился корректно:

    git remote show web

    В ответ должно отобразиться сообщение вида:

    
    * remote web
    Fetch URL: ssh://ixrevo.me/home/i/ixrevo/reasonguide.ru/repo.git/
    Push URL: ssh://ixrevo.me/home/i/ixrevo/reasonguide.ru/repo.git/
  5. И, наконец, пушим наш первый коммит на сервер:

    git push web master

Теперь осталось сделать последний шаг — научить Git распаковывать изменения, пришедшие в репозиторий, и применять их к сайту.

Настраиваем Git post-recieve hook

Для этого мы будем использовать так называемый Git хук (hook англ. крючок, рычаг, комп. специальная процедура, отслеживающая появление некоторого события) — это небольшой скрипт, который вы можете разместить в специальной папке вашего Git репозитория $GIT_DIR/hooks, который будет вызывать определённые действия в ответ на какие-либо события.

А именно, мы будем использовать post-recieve хук, который срабатывает на удалённом репозитории, когда мы выполняем push на локальном репозитории. Чтобы его настроить, нам надо подключиться к серверу по ssh и выполнить следующие действия:

  1. Создать файл с названием post-receive в директории hooks нашего git репозитория:

    nano ~/example.com/repo.git/hooks/post-receive

  2. И вставить в него следующий bash скрипт:

    
    #!/bin/bash
    #
    
    siteroot="/home/i/ixrevo/reasonguide.ru/public_html"
    
    while read oldrev newrev ref
    do
      branch=`echo $ref | cut -d/ -f3`
    
      if [ "master" == "$branch" ]; then
        git archive master | tar -x -C $siteroot
      fi
    done
    

    Этот скрипт будет читать строки из стандартного ввода и записывать первые три слова (по умолчанию разделителем между словами считается пробел) в три переменные: oldrev, newrev и ref. Туда будет приходить что-то вроде:

    aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master

    Затем из переменной ref он будет вырезать имя ветки, которую вы запушили в репозиторий. Если имя ветки совпадает с master, то он будет делать полный архив репозитория и распаковывать его в директорию, которую вы указали в переменной siteroot. Как вы, наверное, догадались, этой директории вместо пути из моего примера "/home/i/ixrevo/reasonguide.ru/public_html" надо указать путь к директории, где находится ваш сайт.

  3. Наконец сделаем файл выполняемым:

    chmod +x ~/example.com/repo.git/hooks/post-receive

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

Деплоймент сайта, по шагам

Теперь с настроенной системой деплоймента ваш workflow (рабочий процесс) предполагает примерно такую последовательность действий:

  1. Вы вносите в код сайта что-то новое, полезное, доброе и вечное.
  2. Тестируете это изменение в своей локальной среде разработки.
  3. Когда вы считаете, что изменения работают именно так, как вы хотели, и ничего не ломают, то делаете commit в систему контроля версий. Все изменения теперь хранятся в Git и для всех изменений всегда можно узнать что, когда, кем, а если вы пишите разумные комментарии к коммитам, то и зачем это было сделано.
  4. Делаете push изменений в репозиторий на сервере и… Бум! Ваши изменения применились к вашему сайту.

Полезные ссылки

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

15 комментариев к записи “Как настроить деплоймент сайта на WordPress с помощью Git”

  1. Спасибо! Пытаюсь разобраться с организацией воркфлоу. Везде пишут какие-то огромные мануалы (с использованием капистрано и т.д.), как будто я ПО для марсохода разрабатываю, а не пытаюсь хоть как-то начать использовать git в веб-разработке

    1. Да я сам, когда разбирался в теме, сталкивался с такими монструозными мануалами, что после них думаешь «а не продолжить ли мне использовать мой старый добрый ftp-клиент и не заморачиваться».

  2. Здравствуйте. Большое спасибо за статью, ничего подобного в сети еще не встречал. Все очень доступно и понятно, но все же у меня возникло несколько вопросов:
    1. Насколько я понял, здесь описывается процесс, как начать рабоатьс GIT с уже созданным сайтом?
    2. если мы переносим сайт на localhost, мы должны исправить базу данных? с помощью SQL заменить пути фаилов с www на localhost?

    1. Я не включал в процесс деплоя базу даных, потому что я использую много плагинов (JetPack, W3 Total Cache и т.д.), которые локально или не работают нормально или мешаются и следовательно базы на локальном компьютере и на live-сервере будут отличаться. Хотя, если переносить только таблицы самого WP… Но это надо подумать.

      А чтобы база с веб-сервера работала на локальной тачке, проще всего в wp-config-local.php добавить такие строчки:

      define('WP_HOME','http://localhost/sitename');
      define('WP_SITEURL','http://localhost/sitename');

      Где http://localhost/sitename ссылка на локальную версию сайта. Это намного проще и надёжней, чем в базе данных что-то менять sql-м или ещё как-то.

      Но если вы хотите править именно в базе данных, то выгрузите дамп в виде файла sql и в текстовом редактором замите по всему файлу http://www.sitename на http://localhost/sitename, но это может поломать настройки, которые хранятся в сериализованных массивах (где длина значения задана).

      Есть ещё вариант использовать плагин http://wordpress.org/plugins/wp-migrate-db/

      Но мне кажется, что проще всего в конфиге прописать, как я выше написал, и не париться.

      1. Спасибо за развернутый ответ. Вроде бы все понятно, однако возник другой вопрос. Если заниматься разработкой сайта локально, а база будет в сети, не будет ли процесс слишком медленным или я не прав?
        На данный момент прокачиваю скил в области фронт-енд, по большой части css+html+javascript. Работаю по старинке, устанавливаю worpress на локалке, довожу сайт до ума, затем заливаю на хостинг и импортирую базу данных с изменениями. Потом правлю и по ФТП загружаю файлы на хостинг. Знакомый программист рассказал, что так делали лет 5 назад. Поэтому заинтересовался ГИТом.
        Что посоветуете как начинающему разработчику? Спасибо.

        1. Мне сложно посоветовать что-то конкретное, потому что подход зависит от решаемой задачи, а «серебряной пули» пока не придумали.

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

          Но опять же, я не знаю всех деталей вашего воркфлоу, и не могу дать окончательный ответ.

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

  3. Уведомление: Хорошая статья про деплоймент сайта на сервер « Yet Another Programming Blog
  4. Здравствуйте. Спасибо за статью.
    У меня такой вопрос: а чем плоха схема, если я размещу .git папку в папке public_html и закрою её от доступа через конфиг веб-сервера, при этом через SSH буду делать pull нужной ветки для обновления сайта после push с локального компьютера? (не считая того, что нужно одну лишнюю команду руками выполнять).

    1. Здравствуйте!

      Думаю, что можно git pull также прописать в post-recieve хуке и лишняя команда не понадобится.

      Теоритически, такая схема имеет право на существование, всё зависит на сколько важно, чтобы никто не получил доступ к репозиторию. .htaccess — это дело хорошее, но то Яндекс случайно Jira проиндексирует свою, то Мегафон смс сообщения, а если репа вне публично доступной папки, то человеческому фактору тут сложнее сыграть свою роль. В смысле, что настройки можно забыть или случайно потереть, а так папка и без настроек недоступна.

      Но в любом случае, я описал лишь частный случай настройки деплоймента, и если вам что-то удобней, то что тут скажешь :)

  5. Спасибо за статью.

    Есть вопрос. Ваш post-receive хук не удаляет файлы, подскажите что подправить, сам не осилю.

    1. Хороший вопрос. Сам с этим столкнулся, но, по-моему, не удаляются файлы только из корня, а в директориях удаляются, хотя тут я не уверен на 100%.

      Можно попробовать добавить к хуку rm, но тут сложно не запутаться, потому что удалять можно только файлы и директории, которые в репозитории хранятся, а те, которые в .gitignore прописаны удалять нельзя.

      Для себя я решил эту проблему, тем что стал хранить в git’е только директорию с темой WordPress и в хуке, перед тем как её выкатить, её удаляю.

      Может будет полезным моя последняя версия git-post-recieve хука

      #!/bin/sh
      #
      
      SITEROOT="/var/www/ixrevo.me/html"
      LIVE="$SITEROOT/wp-content/themes/ixrevo"
      DEV="$SITEROOT/wp-content/themes/ixrevo-dev"
      LOG="/var/www/ixrevo.me/html/wp-content/themes/git-recieve.log"
      DATE=$(date +"%Y-%m-%d %T")
      
      while read oldrev newrev ref
      do
        branch=`echo $ref | cut -d/ -f3`
      
        echo
        echo "$DATE >> $branch has been RECEIVED."
        echo "$DATE >> $branch has been RECEIVED." >> "$LOG"
      
        if test "$newrev" = "0000000000000000000000000000000000000000"
        then
          echo
          echo "$DATE >> Branch: $branch has been DELETED."
          echo "$DATE >> Branch: $branch has been DELETED." >> "$LOG"
          break
        fi
      
        if test "master" = "$branch"
        then
          (cd $LIVE;  rm -rf *)
          git archive master | tar -x -C "$LIVE"
          echo
          echo "$DATE >> Branch: $branch has been DEPLOYED."
          echo "$DATE >> Branch: $branch has been DEPLOYED." >> "$LOG"
        fi
      
        if test "dev" = "$branch"
        then
          (cd $DEV;  rm -rf *)
          git archive dev | tar -x -C "$DEV"
          echo
          echo "$DATE >> Branch: $branch has been DEPLOYED."
          echo "$DATE >> Branch: $branch has been DEPLOYED." >> "$LOG"
        fi
      done
      
      echo
      echo >> "$LOG"
  6. Добрый день!

    Очень полезный мануал. День убил, пока нашел что-то стоящее. Спасибо огромное.

    Вопрос. А возможно ли, при данной конфигурации, настроит еще и обновление файлов с сервера?
    Я имею ввиду — если на сервере в папке блаблаблa/public_html что-то изменилось — чтобы это отображалось в git клиенте? Я пользуюсь gitEye, к примеру.

  7. Благодарю за статью, но я досадно застрял на пункте:

    >>4. Подключаем к локальному репозиторию удалённый, который находится на нашем веб-сервере:
    git remote add web ssh://username@example.com/home/username/example-com.git

    У меня стоит ubuntu через терминал я подключаюсь по ssh на сервер где стоит CentOs и установлен Git, но по вашему примеру я подключиться никак не могу, промучился несколько часов((…

    Подскажите пожалуйста вероятное решение проблемы?

  8. Не понятно мне как вы базу переносите, плагины создают свои таблицы и записи в БД (настройки например)
    гит переносит только файлы
    перенесли вы файлы а базу — нет
    бум и вместо нового сайта получаем кучу ошибок
    что я пропустил?

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