Разделите понятия DEV контейнер и PROD контейнер.
DEV образ не содержит в себе код вашего проекта, он содержит только окружение, а код маунтится через volume. Инженер делает правки у себя лакально, sftp не требуется.
PROD контейнер содержит в себе конкретную версию код со всем и зависимостями, он только запускается для работы в связке с DEV контейнерами.
Например у вас есть сервисы: sa, sb, sc.
В docker-compose.yml вы прописываете 6 сервисов: sa_dev, sa_prod, sb_dev, sb_prod, sc_dev, sc_prod.
Пары *_dev и *_prod живут на одинаковых ip с одинаковыми DNS алиасами, это нужно для того, что бы обеспечить жесткую связь между вашими сервисами и не перехреначивать половину docker-compose.yml
Например вы хотите сделать правки на sb, но sa и sc используются sb. Вы поднимаете:
sa_prod, sb_dev, sc_prod.
Делаете свои правки, проверяете. Когда все ок - коммитите правки и собираете новый образ sb_prod, пушите его в регистр и обновляете версию в docker-compose.yml