2 и 3 легко решаются с помощью указания докрута nginx/apache через симлинк, с хранением всех или последних развернутых версий в отдельных рядом лежащих каталогах, как указал
Евгений Безымянников, но только в случаях или если нет схемы базы, или если она не меняется, или если приложение нормально работает с разными версиями схемы, не вылетая с ошибками типа "нет таблицы/поля" (в разумных пределах).
Иначе по быстрому можно вопрос решить только с остановкой проекта на время миграции, если база не поддерживает неблокирующее изменение схемы или поддерживает, но не для множественных изменений в одной транзакции, а в проекте требуются множественные, типа переноса столбца из одной таблицы в другую. В таких случаях для SQL баз я не нашёл способа реализовать zero-downtime без переработки приложения (триггеры, хранимки, вьюхи и т. п. - тоже часть приложения) такой что, оно либо временно (пока синкаются в фоне старые данные) пишет в две базы, читая из старой, либо определяет какая версия каких таблиц ему доступна.
Проблема в том, что в сколь нибудь нагруженном приложении, постоянно в базу что-то пишущем, нельзя получить мгновенно в новой базе маппинг старой без промежуточных версий приложения, работающих с двумя базами одновременно. То есть по сути zero-downtime деплой новой версии приложения разбивается на деплой двух версий - первая (промежуточная) работает с двумя версиями базы (естественно с проседанием по производительности), во второй работа со старыми отключается, когда данные двух баз полностью будут синхронны..