Реклама ООО Таймвэб
Реклама ООО Таймвэб
Реклама ООО Таймвэб

Полуавтоматический деплой приложения из GIT-репозитория

12 комментариев
Полуавтоматический деплой приложения из GIT-репозитория

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

Современный подход к развёртыванию веб-приложения подразумевает использование Docker'а вкупе с Kubernetes, а тестирование и сборка приложения перед этим происходит в пайплайнах (pipeline) какой-нибудь системы непрерывной интеграции (CI).

Но зачем все эти ресурсоёмкие сложности, если у Вас простой сайт на обычном хостинге, на котором поддержка докера не предусмотрена?

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

Почему git worktree?

Если вы привычным образом склонируете репозиторий в public_html, то рискуете оставить папку с именем .git общедоступной (а это исходный код вашего приложения). На неё придётся прописывать правила в .htaccess или прибегать к иным костылям. В любом случае это небезопасный путь.

С git worktree клон репозитория может находится в укромном местечке, а в отделённой ветке будет файл с именем .git, в котором будет указан только путь до клона.

Кроме того, имея всего один клон репозитория, вы можете выделить из него разные ветки на несколько сайтов. Например, ветка test на тестовую версию сайта, а ветка production на боевую версию.

Настройка хостинга и первичная установка приложения

Папка bin

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

mkdir $HOME/bin
export PATH=$HOME/bin:$PATH

В корневой папке вашего профиля следует создать файл с именем .bash_profile с содержимым:

export PATH=$HOME/bin:$PATH

Вы можете сделать это с помощью следующей консольной команды:

echo "export PATH=\$HOME/bin:\$PATH" > $HOME/.bash_profile

Содержимое .bash_profile будет исполняться SSH-клиентом по умолчанию при подключении.

PHP

Если в своём проекте вы используете PHP, то учтите, что по умолчанию в консоли обычно используется PHP 5.3 (введите php --version, чтобы узнать версию). Для удобства использования в консоли PHP той версии, которая вам нужна, добавьте в папку bin ссылку. На примере PHP 7.2:

cd $HOME/bin; ln /opt/php7.2/bin/php php -s

Теперь php --version вернёт PHP 7.2.15 (примечание: минорная версия может отличаться).

Также разместите в папке bin последнюю версию Composer.

Важно: не забывайте о правах на чтение/запуск исполняемых файлов в папке bin.

Сертификаты

Если ваш проект находится в закрытом git-репозитории, то хосту понадобятся права доступа.

Можно использовать логин и пароль от учётной записи с правами, но мы поступим правильно и сгенерируем Deploy key (ключ, дающий доступ к репозиторию только на чтение).

В консоли пишем:

ssh-keygen -t rsa -f id_rsa

Для каждого сервера (gitlab, bitbucket, github...) можно сгенерировать свой ключ, меняя значение id_rsa параметра -f.

В домашней папке появится папка с именем .ssh, в которой будут находиться сгенерированные приватные и публичные ключи. Создадим файл ~/.ssh/config со следующим содержимым:

Для gitlab:

Host gitlab.com
RSAAuthentication yes
IdentityFile ~/.ssh/id_rsa

Для bitbucket:

Host bitbucket.org
IdentityFile ~/.ssh/id_rsa

Для разных хостов записи с одинаковыми или разными ключами можно совместить в одном файле. Пример:Host gitlabПубличный ключ (содержимое файла id_rsa.pub) необходимо добавить в список ключей развёртывания (Deploy Keys) репозитория.Deploy KeysФорма для добавления ключа развёртывания в GitLab

GIT

На многих хостингах рунета по сей день крутится древний Centos с версией git 1.8.3. Такая старая версия git'a абсолютно нам не подходит. Команда git worktree появилась ещё в 2015 году в git 2.5, а в git 2.7 значительно расширилась по функционалу.

Но не беспокойтесь, на машинах Timeweb предустановлен git 2.7.4.

Подготовим папку ~/git для размещения в ней клонов git-репозиториев и перейдём в неё:

mkdir $HOME/git
cd $HOME/git

Клонируем репозиторий project-name в папку project-dir:

Перед выполнением команды замените путь до git-репозитория и имена ветки и проекта на свои.

git clone --mirror -b master git@gitlab.com:contributor/project-name.git project-dir

где "master" – имя ветки, на которую будет переключен клон по умолчанию (если не указывать, то будет выбрана «основная ветка»).

ВАЖНО: следует указать ту ветку, которая не будет участвовать в разворачиваемых приложениях, т.к. дерево worktree нельзя создать из активной ветки. Например, если у вас есть ветки master, test, production, то следует выбрать master, а test и production будут вскоре развёрнуты.

Как и на многих хостингах, в Timeweb применяется практика с использованием папки public_html в качестве корневой папки сайта (веб-папки проекта). Если у вас мультисайтовый аккаунт (более одного сайта на хосте), то и папок public_html несколько. Например:

  • ~/www-project-name/public_html - для боевого приложения,
  • ~/www-test-project-name/public_html - для тестов.

Названия папок берутся из названий сайтов в админской панели и приведены здесь для примера.

Обычно веб-папка проекта не всегда совпадает с корневой папкой приложения: в веб-папке принято размещать только публичные файлы — JS-скрипты, картинки, стили, шрифты; а также файл скрипта для инициализации приложения. Весь рабочий код остаётся вне веб-папки. Эта практика приводит к единственному решению — public_html должна быть ссылкой на веб-папку проекта. Сам проект можно разместить рядом, в папке branch.

Развернём ветку production. На этом этапе уже пора добавить в админской панели свой сайт www-project-name и вместе с тем создадутся папки ~/www-project-name/public_html. Папку public_html со страницей-заглушкой нужно сразу удалить. Теперь создаём worktree в папке ~/www-project-name/branch:

cd $HOME/git/project-dir
git worktree add $HOME/www-project-name/branch production

Создаём символьную ссылку веб-папки на месте папки public_html, которую вы ранее удалили. В моём примере веб-папка является папкой web в корне проекта, у вас она может отличаться.

ln -s $HOME/www-project-name/branch/web $HOME/www-project-name/public_html

Поскольку в моём приложении есть и ветка test, то таким же образом я разверну и её:

cd $HOME/git/project-dir
git worktree add $HOME/www-test-project-name/branch test
ln -s $HOME/www-test-project-name/branch/web $HOME/www-test-project-name/public_html

Установка приложения

На текущем этапе все файлы нужных веток репозитория проекта размещены в соответствующих каталогах:

~/www-project-name/branchproduction-ветка

~/www-test-project-name/branchtest-ветка

Осталось установить и настроить приложение. Переходим в корневую папку приложения:

cd $HOME/www-project-name/branch

Настройте конфигурационные файлы, которые, кстати, должны быть предварительно добавлены в .gitignore.

Если вы используете пакетные менеджеры, то подтяните необходимые пакеты. Применительно к Composer:

composer install --no-dev

Установите само приложение. Например, если это Yii2:

php yii init
php yii migrate
Комьюнити теперь в Телеграм
Подпишитесь и будьте в курсе последних IT-новостей
Подписаться

VDS Timeweb

Обновление

Приложение развёрнуто. Осталось настроить обновление приложения — вы ведь будете его поддерживать?

Для этого в папке bin создадим скрипт, который будет подгружать изменения из git-репозитория и применять их. На моём сервере это будет файл ~/bin/hi (с правами на запуск):

~/bin/hi

Содержимое файла в моём случае:

echo "Привет!"

echo "";echo "Синхронизация репозитория";
cd $HOME/git/project-dir;git fetch;

echo "";echo "Обновление production";

# переход к файлам приложения
cd $HOME/www-project-name/branch;

# сброс и подгрузка изменений
git reset --hard;git pull origin production;

# установка нужных версий зависимостей
/opt/php7.2/bin/php $HOME/bin/composer install —no-dev;
# к php нужно прописывать полные пути!

# моё приложение поддерживает миграции с бэкапами
/opt/php7.2/bin/php core migrate/up --all --backup;
# для Yii2 это будет ...php yii migrate --interactive=0

echo "";echo "Обновление test";
cd $HOME/www-test-project-name/branch;
git reset --hard;git pull origin test;
/opt/php7.2/bin/php $HOME/bin/composer install --no-dev;
/opt/php7.2/bin/php core migrate/up --all;

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

Такой способ предоставляет обновление в полуавтоматическом режиме. Однако можно настроить и полностью автоматическое обновление приложений, например, сразу после пуша изменений в соответствующую ветку. В этом вам может помочь, например, опция web-push в настройках удалённого репозитория.

Примечание:

Вы, наверно, заметили, что перед подтягиванием обновлений вызывается команда

git reset --hard

Поэтому пользовательские файлы и файлы конфигурации должны быть помещены в .gitignore, чтобы git их не удалил при обновлении.

VDS

echo -e "Все про серверы, сети, хостинг и еще раз серверы" >/dev/pts/0

Комментарии

Ни хрена не понятно... Но очень интересно!
А че с гитхабом примеров нет?
Создание двух веток внутри домена будет считаться за два сайта? Или это в рамках 1го?
Получается БД у теста и продакшена будет одна и таже?
Свернуть ответы
Комментарий автора
roxblnfk +19
10 дек в 2020
> Создание двух веток внутри домена будет считаться за два сайта? Или это в рамках 1го? Получается БД у теста и продакшена будет одна и таже?

Что-то тут не так с терминологией.

"Ветка" относится к системе контроля версий. С доменом (доменным именем) это не пересекается.

Если под "сайтом" подразумевается единица измерения, относящаяся к хостингу и его тарифам, то один сайт это одна публичная папка. Количество БД прописано в тарифе. На тарифе Optimo+, например, неограниченное кол-во БД на 10 сайтов.
На один такой сайт может вести как один домен, так и несколько.

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

> А че с гитхабом примеров нет?

Чемодан не занесли.
Rosh1ck +116
10 дек в 2020
Кажется, что с GitHub можно попробовать один из двух способов или экспериментировать :)

Речь идет про создание двух директорий с проектом. Следовательно к одной привязывается "боевое" доменное имя, а к другой тестовое. Например, поддомен staging.example.com или test.example.com

В контексте данной статьи я так понимаю одна база, но всегда можно попробовать на тестовой версии изменить настройки подключения и выгрузить дамп с боевой базы на тестовую.
Комментарий автора
roxblnfk +19
10 дек в 2020
В статье нет контекста в отношении баз данных.
Вот, кстати, фраза, которая намекает, что каждая ветка приложения может быть индивидуально настроена:

> Настройте конфигурационные файлы, которые, кстати, должны быть предварительно добавлены в .gitignore.

Хотите одну БД на тест и прод - пожалуйста, но я не вижу в этом смысла, т.к. тестовая среда не должна влиять на продуктовую. Разве что использовать префиксы для таблиц или приложение работает в режиме ReadOnly.
Rosh1ck +116
10 дек в 2020
> Хотите одну БД на тест и прод - пожалуйста, но я не вижу в этом смысла, т.к. тестовая среда не должна влиять на продуктовую

Если только это не preproduction :)
Иными словами новый код, но работающий с боевой базой, чтобы проверить как оно на production будет.

Но лучше новую функциональность тестировать отдельно. Тут я полностью согласен.
Комментарий автора
roxblnfk +19
10 дек в 2020
Замечание к статье:

Директив `RSAAuthentication` для файла ~/.ssh/config в случае Gitlab уже устарела и вместо неё следует использовать `PubkeyAuthentication`
Олег +3
20 дек в 2020
Добрый день.

Все же немного не понятно ваше "Важное" замечание:
>> ВАЖНО: следует указать ту ветку, которая не будет участвовать в разворачиваемых приложениях, т.к. дерево worktree нельзя создать из активной ветки. Например, если у вас есть ветки master, test, production, то следует выбрать master, а test и production будут вскоре развёрнуты.

На практике, у меня никаких конфликтов не возникало при использовании имени ветки master в качестве "production". Т.е. следующие команды не вызвали никаких конфликтов (более полу-года уже работает):
$ git clone --mirror -b master git@gitlab.com:contributor/project-name.git project-dir
$ cd $HOME/git/project-dir
$ git worktree add $HOME/www-project-name/branch master

Может есть какие-то подводные камни, которых я не вижу?...
Свернуть ответы
Комментарий автора
roxblnfk +19
20 дек в 2020
Хороший вопрос. Локально у меня на версии 2.29 тоже работает. Возможно, это была проблема версии 2.7 и более ранних. Статью редактировать не могу, поэтому ваш комментарий будет очередной заметкой к статье :)
Максим Филиппов 0
12 апр в 2021
На хостинге Timeweb не работает связка Django <--> mysql. PostgreSQL не предоставляется. А кому сегодня интересно разрабатывать на php? А так да, синхронизация с git работает :)
Свернуть ответы
Комментарий автора
roxblnfk +19
12 апр в 2021
До сих пор разрабатываю на php и мне это интересно :)
А про постгрю скажу так: приложение посерьёзнее блога/лендоса лучше сразу хостить на VDS в контейнерах. Там будет и постгря и всё остальное.
Drozdovsky Boris 0
24 фев в 2022
Идет 2022 год. Читаю статью 2019 года - похоже то, что надо!

Первым делом :
$ git --version
git version 2.17.1

расходимся пацаны...
С помощью соцсетей
У меня нет аккаунта Зарегистрироваться
С помощью соцсетей
У меня уже есть аккаунт Войти
Инструкции по восстановлению пароля высланы на Ваш адрес электронной почты.
Пожалуйста, укажите email вашего аккаунта
Ваш баланс 10 ТК
1 ТК = 1 ₽
О том, как заработать и потратить Таймкарму, читайте в этой статье
Чтобы потратить Таймкарму, зарегистрируйтесь на нашем сайте