Обновление проекта

⏱ 20 мин · 🧩 заданий: 5

Цикл разработки

Компьютер:  код → тесты → git commit → git push
                                          │
Сервер:     git pull → pip install → migrate → collectstatic → restart gunicorn

Никогда не правьте код прямо на продакшен-сервере: изменения потеряются при следующем git pull и не попадут в историю.

Ручное обновление

ssh myblog
cd ~/blog
git pull
source venv/bin/activate
set -a; source .env; set +a
pip install -r requirements.txt
python manage.py migrate
python manage.py collectstatic --noinput
sudo systemctl restart gunicorn

Каждый шаг важен:

Шаг Зачем
git pull Новый код
pip install -r requirements.txt Новые или обновлённые пакеты
migrate Изменения структуры базы
collectstatic Новые или изменённые CSS/JS/картинки
restart gunicorn Python-код и шаблоны загружаются в память процессов один раз — без перезапуска изменения не применятся

Скрипт деплоя

Чтобы не забыть шаг, автоматизируем. ~/blog/deploy.sh:

#!/usr/bin/env bash
set -euo pipefail

cd ~/blog
echo "→ Резервная копия базы"
pg_dump -U blog -h localhost blog | gzip > ~/backups/before-deploy-$(date +%F-%H%M).sql.gz

echo "→ Код"
git pull --ff-only

echo "→ Зависимости"
source venv/bin/activate
set -a; source .env; set +a
pip install -r requirements.txt --quiet

echo "→ Миграции и статика"
python manage.py migrate --noinput
python manage.py collectstatic --noinput
python manage.py check --deploy

echo "→ Перезапуск"
sudo systemctl restart gunicorn
echo "✓ Готово"
chmod +x deploy.sh
./deploy.sh

set -euo pipefail — остановиться при первой ошибке, при обращении к неопределённой переменной и при ошибке в любой части конвейера.

Чтобы sudo systemctl restart gunicorn не спрашивал пароль, разрешите эту команду пользователю deploy (sudo visudo -f /etc/sudoers.d/deploy):

deploy ALL=NOPASSWD: /bin/systemctl restart gunicorn

Запуск с компьютера одной командой:

ssh myblog "~/blog/deploy.sh"

Плавный перезапуск

restart на долю секунды прерывает обслуживание. Gunicorn умеет перезапускать воркеры плавно по сигналу HUP. Добавьте в gunicorn.service:

ExecReload=/bin/kill -s HUP $MAINPID

и используйте sudo systemctl reload gunicorn.

Если что-то пошло не так

sudo journalctl -u gunicorn -n 100      # последние логи
git log --oneline -5                    # что выкатили
git checkout <предыдущий-коммит>        # откат кода
sudo systemctl restart gunicorn

Откат миграций: python manage.py migrate blog 0007 (к нужной миграции) — поэтому и нужна копия базы перед деплоем.

Куда двигаться дальше

  • CI/CD: GitHub Actions запускает тесты на каждый push и выкатывает проект на сервер по SSH автоматически.
  • Docker: проект и все зависимости в контейнерах, одинаковая среда на компьютере и сервере.
  • Мониторинг: Sentry для ошибок, UptimeRobot для проверки доступности.

Итог

  • Обновление: git pull → pip install → migrate → collectstatic → перезапуск Gunicorn.
  • Скрипт deploy.sh с set -euo pipefail и копией базы делает выкладку надёжной.
  • Плавный перезапуск — reload с сигналом HUP.
  • Логи и git помогают быстро откатиться.

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Расставить по порядку

Расставьте шаги обновления проекта на сервере.

  1. cd ~/blog && git pull
  2. python manage.py migrate
  3. source venv/bin/activate
  4. pip install -r requirements.txt
  5. sudo systemctl restart gunicorn
  6. python manage.py collectstatic --noinput
Задание 2 Один вариант ответа

Вы поменяли только шаблон. Что обязательно сделать на сервере после git pull, чтобы изменения появились?

Задание 3 Написать код

Напишите скрипт deploy.sh: остановка при любой ошибке (set -e), переход в ~/blog, git pull, активация окружения, установка зависимостей, миграции, сборка статики без вопросов и перезапуск gunicorn.

Задание 4 Несколько вариантов

Какие практики делают обновления безопаснее?

Задание 5 Один вариант ответа

Что делает sudo systemctl reload gunicorn в отличие от restart (для сервиса с ExecReload=/bin/kill -s HUP $MAINPID)?

Войдите, чтобы отмечать пройденные уроки.