Comments 49
Именно так работает сайт erlyvideo.ru/ (он же и erlyvideo.org/)
Из одной папки в гите берутся файлы, выбирается русский или английский вариант и смотрим.
Из одной папки в гите берутся файлы, выбирается русский или английский вариант и смотрим.
-25
Спасибо, хороший пост. Отличная идея: хранить рабочую копию сайта и bare-репозиторий отдельно. Применяли ли вы ваш метод на практике?
+1
Да, так работает webstandardsdays.ru, например.
+1
-1
Я как раз на прошлой сделал что-то похожее на Mercurial.
Смысл такой: к существующей системе контроля версий добавился репозиторий на тестовом сервере, в котором стоит хук на пуш. Поэтому для обновления версии достаточно выбрать удалённый репозиторий и ввести логин-пароль (отличающийся от пароля в рабочем репозитории, чтобы избежать случайного пуша куда не надо).
Смысл такой: к существующей системе контроля версий добавился репозиторий на тестовом сервере, в котором стоит хук на пуш. Поэтому для обновления версии достаточно выбрать удалённый репозиторий и ввести логин-пароль (отличающийся от пароля в рабочем репозитории, чтобы избежать случайного пуша куда не надо).
+3
У меня в кроне стоит так:
* * * * * cd /home/project/project/ && /usr/bin/hg -q pull && /usr/bin/hg update production | grep -v «0 files updated, 0 files merged, 0 files removed, 0 files unresolved» && /bin/touch web/django.wsgi
Причем на разных нодах разное время запуска крона. Это делалось специально, что б перезапуск серверов на нодах не происходил одновременно, т.е. достигается нулевой общий даунтайм. Ну и еще пара нод обновляется раз в полчаса, что б если все-таки было накосячено, успеть за мат-ожидание исправить проблему.
Не делал хуков на push (или всякие fabric'и) именно по причине требования к нулевому общему даунтайму.
Ну а само обновление продакшн-нод досигается просто перемещением метки production на нужную ревизию.
* * * * * cd /home/project/project/ && /usr/bin/hg -q pull && /usr/bin/hg update production | grep -v «0 files updated, 0 files merged, 0 files removed, 0 files unresolved» && /bin/touch web/django.wsgi
Причем на разных нодах разное время запуска крона. Это делалось специально, что б перезапуск серверов на нодах не происходил одновременно, т.е. достигается нулевой общий даунтайм. Ну и еще пара нод обновляется раз в полчаса, что б если все-таки было накосячено, успеть за мат-ожидание исправить проблему.
Не делал хуков на push (или всякие fabric'и) именно по причине требования к нулевому общему даунтайму.
Ну а само обновление продакшн-нод досигается просто перемещением метки production на нужную ревизию.
+2
А зачем закрывать через .htaccess папку .git когда можно использовать detached рабочий каталог и хранить сам репозиторий в недоступном для веб-сервера месте?
Опция --work-tree служит для этой цели. www.kernel.org/pub/software/scm/git/docs/
Опция --work-tree служит для этой цели. www.kernel.org/pub/software/scm/git/docs/
+10
Зачем?! Зачем использовать систему контроля версия для деплоя?!
Вас ничему история не учит? http://habrahabr.ru/blogs/infosecurity/70330/
Нет, я, конечно, прочитал, что в статье есть предложение по закрытию доступа к .git директории, но что, если админ ошибется и не сможет правильно настроить mod_rewrite (или правила nginx)?
Почему для деплоя не пользоваться утилитами, специально для этого предназначенными? К примеру, тот же Capistrano (а еще лучше capistrano-ext со стейджингом, чтобы случайно не деплойнуть на продакшн неподготовленный код).
Вас ничему история не учит? http://habrahabr.ru/blogs/infosecurity/70330/
Нет, я, конечно, прочитал, что в статье есть предложение по закрытию доступа к .git директории, но что, если админ ошибется и не сможет правильно настроить mod_rewrite (или правила nginx)?
Почему для деплоя не пользоваться утилитами, специально для этого предназначенными? К примеру, тот же Capistrano (а еще лучше capistrano-ext со стейджингом, чтобы случайно не деплойнуть на продакшн неподготовленный код).
0
Ну… с гитом подобной проблемы, как у svn, нет. Достаточно только, чтобы DocumentRoot хоста находился внутри каталога проекта, или вообще в отдельном каталоге.
Все свои потроха гит содержит аккуратно, не разбрасывая их по подпапкам проекта.
Все свои потроха гит содержит аккуратно, не разбрасывая их по подпапкам проекта.
+6
Для небольших проектов специальные утилиты потребуют слишком много лишних и непонятных телодвижений. Вариант с --work-tree мне нравится намного больше.
+2
А в статье где-нибудь указано, что данный подход желательно применять только на небольших проектах?
И еще, настройка репозиториев, хуков, mod_rewrite, а также системы сообщения между prime и hub репозиториями затмит собой настройку скрипта для capistrano и пробросу пары ключей между машинами :)
И еще, настройка репозиториев, хуков, mod_rewrite, а также системы сообщения между prime и hub репозиториями затмит собой настройку скрипта для capistrano и пробросу пары ключей между машинами :)
0
я в отличие от автора с двумя репами, сделал один реп с бранчами мастер (в который пушу) и продакшн (который чекаутнут на сервере). далее deploy.sh:
а сколько строк в вашем капистрано-конфиге?
git checkout master
git merge newfeature
git merge bugfix
git push server master
ssh xxx@librapost.ru "cd /xxx/xxx/librapost && git merge master"
а сколько строк в вашем капистрано-конфиге?
-2
ах да. public-папка проектов всегда внутри репа (не корневая), поэтому никаких мод-реврайтов не нужно
-2
Поищите на гитхабе строчку «git ftp»
0
как-то не правильно. Лучше использовать capistrano или подобное, ну на крайний случай делать экспорт в нужный каталог по hook'у.
+4
я свои рельсы уже пару лет деплою через гит, и мне, честно говоря, пользователей капистраны немного жалко.
0
Откатите продакшен на 1 версию назад находясь на рабочей машине. Через git деплоить хорошо, да, но не так как это сделал автор, зачем второй репозиторий? Делать экспорт прямо из bare в нужный каталог.
> пользователей капистраны немного жалко.
Вы просто не умеете ее готовить. Тоже самое говорят хомячки про пользователей unix like os и эникейщики про сервера на unix like.
> пользователей капистраны немного жалко.
Вы просто не умеете ее готовить. Тоже самое говорят хомячки про пользователей unix like os и эникейщики про сервера на unix like.
0
Вы кажется не поняли метафору…
> выше я написал, что в отличие от автора у меня один реп, да.
Тоже как-то не так вас…
git archive master | tar -x -C /somewhere/else
ну или так:
git-archive --format=tar --remote=ssh://remote_server/remote_repository master | tar -xf — в пост-апдейт хук и все.
> deploy.sh:
git checkout master
git merge newfeature
git merge bugfix
git push server master
git алисы вы не осилили, ога.
> выше я написал, что в отличие от автора у меня один реп, да.
Тоже как-то не так вас…
git archive master | tar -x -C /somewhere/else
ну или так:
git-archive --format=tar --remote=ssh://remote_server/remote_repository master | tar -xf — в пост-апдейт хук и все.
> deploy.sh:
git checkout master
git merge newfeature
git merge bugfix
git push server master
git алисы вы не осилили, ога.
+2
зачем мне алиасы там, где я не ввожу команды руками?
ваш вариант с гит-архивом я вообще понять не могу. зачем мне делать на сервере отдельно папку с репом (в который всё равно для деплоя надо будет пушить), и отдельно папку, в которую будет разархивироваться деплой? и что мне делать, если у меня в свежем деплое найдётся критикал баг, и надо будет срочно откатиться назад? иметь в продакшене рабочий реп тоже полезно.
метафору я понял. только вот не понял, зачем вы её здесь привели. удобство капистраны настолько субъективная вещь, что сравнивать её с *nix системами — как сравнивать тех, кто не любит анчоусы с теми, кто не ест жирное.
ваш вариант с гит-архивом я вообще понять не могу. зачем мне делать на сервере отдельно папку с репом (в который всё равно для деплоя надо будет пушить), и отдельно папку, в которую будет разархивироваться деплой? и что мне делать, если у меня в свежем деплое найдётся критикал баг, и надо будет срочно откатиться назад? иметь в продакшене рабочий реп тоже полезно.
метафору я понял. только вот не понял, зачем вы её здесь привели. удобство капистраны настолько субъективная вещь, что сравнивать её с *nix системами — как сравнивать тех, кто не любит анчоусы с теми, кто не ест жирное.
0
А как производите обновление БД?
0
UFO just landed and posted this here
С моей точки зрения это очень не правильный подход. При данном подходе все новые изменения сразу попадут на продакшн сервер. А если в этих изменениях будет регрессионные ошибки? Они сразу положат продакшн сервер… Для того что бы изменения не убили продакшн сервер, умные люди придумали вехи и версии, которые в репозитории будут отмечены тэгами. Продакшн сервер нужно обновлять только на определенный тэг, содержащий фиксированное число изменений проверенных тестировщиками. Таким образом вы сможете более менее гарантировать качество кода и сайта в целом. Описанный у вас способ подходит для деплоя на девелопмент сервер и в меньшей мере на стэйджинг сервер.
0
да, согласен, так и надо делать, но статья предлагает другой подход, который заключается в моментальном обновлении продакшн сервера при любом пуше.
0
промазал, этот комментарий — ответ на http://habrahabr.ru/blogs/Git/127213/#comment_4200113
0
как разрешаются конфликты при git pull?
этой проблемы не возникает, если с девелоперского сайта делать git push на продакшн.
этой проблемы не возникает, если с девелоперского сайта делать git push на продакшн.
0
#!/bin/bash
txtrst='\e[0m' # Text Reset
txtred='\e[0;31m' # Red
txtgrn='\e[0;32m' # Green
WORK_TREE='/some/path/on/dev/server/'
while read oldrev newrev ref
do
case $ref in
refs/heads/dev )
echo "========================================"
git --work-tree=$WORK_TREE checkout -f dev
if [ $? -eq 0 ]; then
echo -e "${txtgrn}DEVELOPER SERVER successfully updated${txtrst}"
else
echo -e "${txtred}Failed to checkout DEVELOPER SERVER!${txtrst}"
fi
;;
refs/heads/master )
echo "========================================"
git push gsl master:master
if [ $? -eq 0 ]; then
echo -e "${txtgrn}PRODUCTION SERVER successfully updated${txtrst}"
else
echo -e "${txtred}Failed to push to PRODUCTION SERVER!${txtrst}"
fi
;;
* )
echo "NO UPDATES FOR $1"
;;
esac
done
echo "========================================"
вот мой post-receive hook на девелоперском сервере.
принцип работы: есть две ветки — master и dev. изменения в ветке dev checkout'ятся в DOCUMENT_ROOT девелопеского сервера. А изменения в ветке master push'атся в bare-репозиторий на продакшн-сервере, а оттуда уже аналогичным образом chekout'ятся в его DOCUMENT_ROOT
0
Деплоить должен человек. Руками. Если оставить это на хук то в один прекрасный момент вы получите неработающий продакшн. А делать исправления на работающем сервере и заливать их в репозиторий — это вообще за гранью добра и зла! Вы там что, на Друпале пишете??
+5
Пытаюсь найти еще информацию по теме выкладывания новой версии на продакшен, но не могу найти.
Подскажите ключевые слова :)
Подскажите ключевые слова :)
0
Я как-то пока что не особо с джитом, поэтому вопрос: операция деплоя в данном случае атомарна? Если нет, тогда не вижу смысла в ней принципе, не говоря уже об habrahabr.ru/blogs/Git/127213/#comment_4200454
+1
а у вас что, часто соединение обрывается во время деплоя? при чём здесь атомарность?
-1
Не, меня интересует, на новые исходники сайт переключается атомарно или в какой-то момент времени половина сырцов предыдущей ревизии, а половина — новой ревизии.
Мы себе не можем позволить обновлять файлы прямо в живом каталоге проекта на сервере.
Поэтому у нас сначала льется на сервер архив, который распаковывается в новую папку и потом производится переключение на эту папку.
Кроме того, не можем себе позволить удалить старые файлы, потому что на них еще могут какие-то кроны работать.
Мы себе не можем позволить обновлять файлы прямо в живом каталоге проекта на сервере.
Поэтому у нас сначала льется на сервер архив, который распаковывается в новую папку и потом производится переключение на эту папку.
Кроме того, не можем себе позволить удалить старые файлы, потому что на них еще могут какие-то кроны работать.
+1
у меня несколько сотен файлов в гите меняется за доли секунды. но тут же зависит от языка и фреймворка. и такой вопрос, а нельзя отрубать сервер и кроны на секунды во время деплоя? zero-downtime-deploy в конце концов?
ну и последний вопрос: а где вы вообще нашли такой инструмент, который моментально атомарно несколько сотен файлов может заменить? на это как-то даже и современные файловые системы не способны. да одновременно сменить сотни записей даже совеменные БД не очень умеют атомарно
ну и последний вопрос: а где вы вообще нашли такой инструмент, который моментально атомарно несколько сотен файлов может заменить? на это как-то даже и современные файловые системы не способны. да одновременно сменить сотни записей даже совеменные БД не очень умеют атомарно
0
У нас за доли секунды несколько сотен запросов на сервера приходит…
Во время деплоя ничего отрубать нельзя.
В нашем случае не нужно заменять атомарно несколько сотен файлов, нужно просто переключить проект на другую папку после того, как в этой папке есть всё нужное для работы проекта. И это происходит вполне себе атомарно. Кроны остаются работать в старых каталогах, но в следующий раз уже запустятся из нового каталога.
В общем, мы сейчас о немного разных вещах говорим… Наверное, нужно было просто разобраться немного в джите и не задавать того вопроса :)
Во время деплоя ничего отрубать нельзя.
В нашем случае не нужно заменять атомарно несколько сотен файлов, нужно просто переключить проект на другую папку после того, как в этой папке есть всё нужное для работы проекта. И это происходит вполне себе атомарно. Кроны остаются работать в старых каталогах, но в следующий раз уже запустятся из нового каталога.
В общем, мы сейчас о немного разных вещах говорим… Наверное, нужно было просто разобраться немного в джите и не задавать того вопроса :)
0
Вообще-то речь не про «одновременно», а про «атомарно». Вариант с изменением рабочего каталога — операция хоть и атомарная, но не решает проблему атомарного обновления частей проекта, которые находятся вне рабочего каталога (база данных, настройки cron, почтовые хуки в ~/.qmail, etc.).
Наша deploy-система блокирует проект, обновляет файлы, структуру базы, настройки cron, перезапускает отдельные сервисы, etc. а потом снимает блокировку. Это гарантирует, что в процессе обновления не получится так, что часть файлов/базы уже обновилась, часть ещё нет, и тут приходит запрос пользователя и он обрабатывается смесью старого и нового кода с в принципе непредсказуемыми последствиями. Кроме того, это гарантирует, что если обновление затянется или сломается в процессе, то пользователь получит статическую страничку «server maintenance, please try again later».
Системы контроля версий всё это делать не умеют и они вообще не предназначены для реализации deploy. Можно, конечно, навесить на них сложные системы хуков и получить почти то, что требуется, но это сложно и не правильно. Для deploy нужно использовать предназначенные для этого системы. И выкатывать новую версию на production сервер нужно ручками, а не автоматически (не в том смысле, что файлы/базу ручками обновлять, а в том смысле, что во-первых желательно перед обновлением глазками просмотреть все изменения — т.е. patch/sql/etc.-файлы — и во-вторых присутствовать при установке этих изменений на сервере на случай если что-то пойдёт не так).
Единственная сложность такого надёжного подхода в том, что все приложения проекта (cgi-шки, fastcgi-сервер, сервисы, cron-скрипты, qmail-скрипты, консольные утилиты) должны поддерживать единую систему блокировок, чтобы было возможно их всех одним махом заблокировать на время обновления системы (все приложения ставят shared-lock в процессе работы, а при обновлении ставится exclusive-lock). Но при наличии таких блокировок решается не только проблема атомарного обновления проекта, но и консистентного бэкапа.
Наша deploy-система блокирует проект, обновляет файлы, структуру базы, настройки cron, перезапускает отдельные сервисы, etc. а потом снимает блокировку. Это гарантирует, что в процессе обновления не получится так, что часть файлов/базы уже обновилась, часть ещё нет, и тут приходит запрос пользователя и он обрабатывается смесью старого и нового кода с в принципе непредсказуемыми последствиями. Кроме того, это гарантирует, что если обновление затянется или сломается в процессе, то пользователь получит статическую страничку «server maintenance, please try again later».
Системы контроля версий всё это делать не умеют и они вообще не предназначены для реализации deploy. Можно, конечно, навесить на них сложные системы хуков и получить почти то, что требуется, но это сложно и не правильно. Для deploy нужно использовать предназначенные для этого системы. И выкатывать новую версию на production сервер нужно ручками, а не автоматически (не в том смысле, что файлы/базу ручками обновлять, а в том смысле, что во-первых желательно перед обновлением глазками просмотреть все изменения — т.е. patch/sql/etc.-файлы — и во-вторых присутствовать при установке этих изменений на сервере на случай если что-то пойдёт не так).
Единственная сложность такого надёжного подхода в том, что все приложения проекта (cgi-шки, fastcgi-сервер, сервисы, cron-скрипты, qmail-скрипты, консольные утилиты) должны поддерживать единую систему блокировок, чтобы было возможно их всех одним махом заблокировать на время обновления системы (все приложения ставят shared-lock в процессе работы, а при обновлении ставится exclusive-lock). Но при наличии таких блокировок решается не только проблема атомарного обновления проекта, но и консистентного бэкапа.
0
У нас вот SQL база особо часто не обновляется да и вообще, по большей части, уходим от SQL решений в последнее время, так что проект не приходится останавливать по причине обновления. Да и даже если обновляется, то обычно это добавление поля в табличку или новой таблички, а значит можно сначала базу обновить, не останавливая или, в крайнем случае, блокируя по частям (а значит проект будет работать, максимум какое-то относительно небольшое количество пользователей получит информацию о server maintenance), а уже потом можно и код, работающий с БД, обновить.
0
на мой вкус я бы при ините добавил shared,
если предполагается, что пушить в bare будут несколько человек:
или даже сделать так после init:
еще обновить server-info лучше сразу после первого пуша руками так:
а в post-receive делать так:
если предплолагается, что в репозитории есть субмодули.
если предполагается, что пушить в bare будут несколько человек:
git --bare init --shared
или даже сделать так после init:
cd ..
sudo chown -R www-data:www-data site_hub.git
sudo chmod -R g+wX,o= site_hub.git
sudo find site_hub.git -type d -exec chmod g+s '{}' ';'
еще обновить server-info лучше сразу после первого пуша руками так:
git update-server-info
а в post-receive делать так:
cd /home/okertanov/public_html/html-templates.espectrale.com/public || exit
#unset GIT_DIR
#unset GIT_WORK_TREE
env -i git pull origin #or whatever
env -i git update-server-info
env -i git submodule init
env -i git submodule update
если предплолагается, что в репозитории есть субмодули.
0
Прошу при первом упоминании слова bare, упомянуть в скобочках, что это «репозиторий без собственной рабочей копии»
0
У нас на «prime» заливается по ftp с помощью модуля ftp для hg. Хук на «hub» у всех репов такой: changegroup = hg update -C; hg ftp -r tip -u. Заливаются не все файлы, а только изменившиеся (это и делает модуль ftp).
Тут чуть подробнее: edhel.krasu.ru/node/328
Тут чуть подробнее: edhel.krasu.ru/node/328
+1
Извините, возможно мой вопрос покажется странным, но я пока не могу управиться с правами на директории/файлы при работе через гит.
Например у меня есть сайт который разрабатывается через гит. Над сайтом работают 3 разработчика, все ходят по ssh.
Ситуация:
Первый разработчик изменяет/создает файл в своем локальном репозитории, коммитит, пушит в bare репозиторий, идет на рабочий сайт и делает pull в результате первый разработчик становится хозяином файла. Потом надо второму разработчику работать с этим же файлом, но он не может его править, т.к. он не хозяин. Можно добавить разработчиков в одну группу, но гит вроде бы создает файлы с правами 644. Плюс ко всему файлы могут создаваться апачем. Может кто нибудь подскажет как решить этот вопрос? Может я что-то упускаю?
Например у меня есть сайт который разрабатывается через гит. Над сайтом работают 3 разработчика, все ходят по ssh.
Ситуация:
Первый разработчик изменяет/создает файл в своем локальном репозитории, коммитит, пушит в bare репозиторий, идет на рабочий сайт и делает pull в результате первый разработчик становится хозяином файла. Потом надо второму разработчику работать с этим же файлом, но он не может его править, т.к. он не хозяин. Можно добавить разработчиков в одну группу, но гит вроде бы создает файлы с правами 644. Плюс ко всему файлы могут создаваться апачем. Может кто нибудь подскажет как решить этот вопрос? Может я что-то упускаю?
0
Вам надо пулить от имени веб-сервера.
Как лучше это сделать зависит от вашей ситуации.
Можно на веб-сервере скрипт сделать, можно по задачке в кроне отслеживать, можно еще вариантов придумать.
Как лучше это сделать зависит от вашей ситуации.
Можно на веб-сервере скрипт сделать, можно по задачке в кроне отслеживать, можно еще вариантов придумать.
0
Дело в том, что в некоторых директориях апач не должен иметь право на изменение файлов, а разработчики наоборот должны иметь право на изменение файлов в этих директориях. Пока решение такое — использовать setfacl и определять через него кто будет писать, а кто нет. С помощью setfacl для файла/директории можно будет указать сразу несколько хозяев и несколько групп. И ночью в определенное время, по крону, восстанавливать права на файлы.
0
Sign up to leave a comment.
Git и публикация сайта