Многоэтапная сборка использует несколько FROM в одном Dockerfile. На этапе сборки устанавливают инструменты и получают артефакты, а в финальный образ копируют только необходимые для запуска файлы через COPY --from. Это позволяет исключить компиляторы и временные файлы из runtime-образа. Интерпретатор, runtime-библиотеки и зависимости приложения всё равно должны присутствовать.
Что такое многоэтапные сборки (multi-stage builds)?
Как отделить инструменты сборки от среды запуска в Docker и какие зависимости нельзя забывать при переносе Ruby-приложения.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
В многоэтапном Dockerfile каждая инструкция FROM начинает новый этап. Этапам можно дать имена, например build и runtime, а нужные результаты переносить через COPY --from=build. Финальный образ не обязан содержать все файлы и инструменты предыдущего этапа. Многоэтапные сборки Docker.
Для Ruby-приложения на этапе сборки могут понадобиться компилятор и заголовочные файлы для нативных gem-зависимостей. На финальном этапе нужны Ruby, код приложения, установленные gems и системные библиотеки, с которыми они связаны. Например, если Bundler действительно установил gems в /usr/local/bundle, соответствующий фрагмент переноса выглядит так:
COPY --from=build /usr/local/bundle /usr/local/bundle
Это только часть Dockerfile: отдельно задают рабочий каталог, копируют приложение и выбирают команду запуска. Нельзя считать, что rake build всегда создаёт готовое приложение в /app/build: содержание Rake-задач определяется конкретным проектом. Также нельзя перенести нативные gems между несовместимыми версиями Ruby, архитектурами или системными библиотеками и ожидать, что всё заработает.
Основная выгода — меньший runtime-образ и меньше ненужных инструментов внутри него. Но multi-stage сам по себе не гарантирует безопасность: обновления базового образа, непривилегированный пользователь и аккуратная работа с секретами остаются отдельными задачами. Пароли и токены не следует встраивать в слои сборки. Зависимости фиксируют, а совместимость конечного образа проверяют именно в его среде. Рекомендации Docker по сборке.