>> Обновление происходит так: мы поднимаем контейнер из нового образа, дожидаемся, пока он полностью прогрузится, и тогда уже гасим старый.
> Не, ну так, конечно, можно, в стиле "fastcgi php до появления php-fpm". Да нет, тут тот же самый php-fpm, только он раскидан по нескольким контейнерам/машинам/нодам. В каждом контейнере, по идее, висит воркер, который дожидается соединений. И да, тот же php-fpm туда впихнуть -- да пожалуйста, было бы желание.
> 1) дроп соединений, ожидающих ответа от первого контейнера в момент переключения. Тут
> можно выкрутиться конструкцией вида "добавляем в конфиг балансировщика второй контейнер,
> метим первый как down, дожидаемся, пока первый закончит обработку всех соединений,
> прибиваем первый", но как-то сложновато получается.
Нет, ну почему же. Дроп соединений делать не нужно. Процедуру вырубания контейнера надо описать корректно, чтобы он дожидался завершения текущих соединений и не принимал новых. По части "не принимал новых" -- тут конечно же надо балансировщик. Но исправление конфига -- опять же, чересчур. Не надо описывать воркеры в конфиге. Надо, чтобы балансировщик узнавал о воркерах через service discovery. Zookeeper/etcd в помощь.
> 2) если приложение - древний монолит, могут возникнуть проблемы с конкурентным доступом
> к ресурсам из обоих контейнеров. Это, конечно, из разряда "не программируйте
> так", но если бы все хорошо программировали...
Да, обычно приходится много чего переписать, чтобы обеспечить бесперебойную работу. Ну, что поделать. Есть игрушки "на коленке", когда нужно сделать быстро. А есть игрушки "на экспорт", когда нужно сделать надёжно.