2011-12-20 3 views
3

У меня есть проект Django, работающий внутри virtualenv без пакетов сайтов. Когда дело доходит до ввода моих новых изменений на сервер, я хотел бы создать новый каталог virtualenv, установить мой проект и все его зависимости, а затем быстро переименовать два каталога virtualenv ТОЛЬКО, если новый код будет успешно развернут.django + virtualenv = атомное обновление - возможно ли это?

Все отлично работает на бумаге, пока вы не переименуете каталог virtualevn. Параметр Relocate на virtualenv не является надежным в соответствии с его документацией.

Как вы предлагаете модернизировать мой проект ТОЛЬКО, если новый код окажется пригодным для развертывания.

Вот шаги:

# fab update_server to run the following: 
cd /srv/myvenv # existing instance 
cd ../ 
virtualenv myenv-1 
source myenv-1/bin/activate 
git co http://my.com/project 
pip install -r project/req.txt 
# all worked 
mv myenv myenv-2; mv myenv-1 myenv 
touch /path/proj.wsgi # have apache to reload us 

выше совершенен, но переименование или перемещение virtualenv не является надежным.

Обновление сайта в режиме myvenv требует времени и может также сломать сайт.

Как вы это сделаете? Строить?

+0

* Опция relocate для virtualenv не надежна в соответствии с ее документацией * извините, не могли бы вы объяснить это заявление? Что конкретно не является надежным? '--relocatable' звучит точно так, как вам нужно. –

+0

--relocatable отмечен как экспериментальный. Я не могу полагаться на это на производстве. – un33k

ответ

4

Я делаю это с символическими ссылками и полностью отдельными каталогами релизов. Т.е. развертывание включает клонирование всего проекта в новый каталог, построение виртуального пространства внутри него, а затем переключение символической ссылки «production» в точку в этом каталоге.

Моя раскладка в основном

/var/www/myapp/ 
       uploads/ 
       tmp/ 
       releases/ 
         001/myapp/ 
         002/myapp/ 
         003/myapp/ 
           ve/ 
           ...etc in each release directory... 
       myapp # symlink to releases/003/myapp/ 

Так что, когда я раскрываю к производству, мои сценарии развертывания RSync совершенно новая копия на /var/www/myapp/releases/004/myapp/, построить virtualenv там, установить все пакеты в него, а затем

rm -f /var/www/myapp/myapp 
ln -s /var/www/myapp/releases/004/myapp/ /var/www/myapp/myapp 

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

Каждая внешняя ссылка (в файлах конфигурации apache или wsgi-файлах или что-то еще) указывает на библиотеки и двоичные файлы в virtualenv как /var/www/myapp/myapp/ve/. Я также избегаю использования source ve/bin/activate и вместо этого укажу на полный путь в файлах конфигурации, и я редактирую manage.py, чтобы использовать #!ve/bin/python, поэтому я могу запускать команды с ./manage.py whatever, и он будет работать без меня, если я буду помнить, активировал ли я виртуальный виртуальный.

+2

Технически между «rm» и «ln» Apache может пропустить запрос, потому что сценарий WSGI отсутствует. Чуть более безопасный метод заключается в том, чтобы иметь простой скрипт WSGI вне пакета и настроить его sys.path где-то в реальном местоположении проекта и импортировать модуль оттуда, который устанавливает фактическое приложение WSGI. При обновлении создайте новый файл сценария WSGI с новым путем в нем и «mv» вместо существующего. Команда «mv» должна быть атомарной, если изменить файловую систему. –

+0

Грэм, это отличная идея. Я посмотрю, смогу ли я работать в этом процессе.Я не обманывал себя, думая, что мой подход является строго атомарным, просто большое улучшение по сравнению с тем, что приложение сломано на время сборки virtualenv. – thraxil

+2

На самом деле, 'rm' вовсе не требуется. Вы можете использовать 'ln -sf' для принудительного удаления предыдущей существующей символической ссылки. –