Что означает инструкция FROM scratch в Dockerfile?

Ответ

Инструкция FROM scratch в Dockerfile указывает на создание образа с абсолютно пустой файловой системой. Это специальный, минимально возможный базовый образ, который не содержит никаких файлов, библиотек, утилит или даже стандартных директорий, таких как /bin или /lib.

Преимущества использования

  1. Минимальный размер: Образ содержит только ваше приложение и его зависимости, что значительно уменьшает его размер, ускоряя загрузку, передачу и развертывание.
  2. Повышенная безопасность: Отсутствие shell-оболочки, системных утилит и библиотек резко сокращает поверхность атаки на контейнер.

Основные сценарии использования

  • Статически скомпилированные приложения: Идеально подходит для приложений, написанных на Go, Rust или C++, которые компилируются в один бинарный файл без внешних зависимостей.
  • Создание собственных базовых образов: Используется как отправная точка для построения кастомных базовых образов с нуля.

Пример для Go-приложения

# Этап 1: Сборка приложения
FROM golang:1.19 as builder
WORKDIR /app
COPY . .
# Собираем статически скомпилированный бинарник
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp .

# Этап 2: Создание минимального образа
FROM scratch
# Копируем только скомпилированный файл из сборщика
COPY --from=builder /app/myapp .
# Запускаем приложение
CMD ["/myapp"]

Ключевые особенности

  • В образе отсутствует shell (/bin/sh), поэтому инструкции RUN, CMD и ENTRYPOINT должны использовать exec-форму в виде JSON-массива (например, CMD ["/myapp", "--arg"]).
  • Нет никаких стандартных утилит (ls, cat) или пакетных менеджеров (apt, apk).

Ответ 18+ 🔞

Да ты посмотри, что творят, блядь! Вот эта самая FROM scratch в Dockerfile — это ж просто пиздец какой минимализм, в рот меня чих-пых! Это не образ, а чистое, блядь, ничто. Пустота. Как твоя голова после пятницы.

Представь: нет там ни /bin, ни /lib, ни одной ёбаной библиотеки. Никакого шелла, чтобы покомандовать, никакого ls, чтобы посмотреть, что натворил. Абсолютный ноль, вакуум, блядь. Создали образ — и там только твоё приложение торчит, как хуй в проруби.

И зачем это, спрашивается, нахуй?

А вот зачем, умник:

  1. Размер, блядь! Образ получается овердохуища маленький. Не 700 мегабайт с кучей хлама, а ровно столько, сколько весит твой бинарник. Качает, разворачивает — всё мгновенно.
  2. Безопасность, ёпта! Атаковать нечего, блядь! Нет шелла — не зайти. Нет лишних утилит — не сломать. Контейнер как танк, только внутри один стрелок сидит.

Кому это впизду нужно?

В основном, конечно, всяким гоферам, растам и прочим цэплюсникам. У них приложение компилируется в один жирный бинарник, который сам по себе, как слон, и ему от системы нихуя не надо. Вот его и суют в этот scratch.

Смотри, как это выглядит на практике, блядь:

# Этап первый: собираем всё, как обычно
FROM golang:1.19 as builder
WORKDIR /app
COPY . .
# Компилим так, чтобы бинарник был самодостаточный, блядь
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp .

# Этап второй: магия начинается
FROM scratch
# Берём из предыдущего этапа только готовый бинарник
COPY --from=builder /app/myapp .
# И запускаем его
CMD ["/myapp"]

Видишь? Из первого, навороченного образа мы вытащили только готовый myapp и положили его в пустоту. Всё, пиздец. Образ готов.

Но есть нюанс, ёбаный в рот!

Там же нет шелла, блядь! Поэтому команды CMD и ENTRYPOINT обязательно пиши в JSON-формате, вот так: CMD ["/myapp", "--arg"]. Если напишешь как строку CMD /myapp, Docker попытается вызвать /bin/sh -c, а его-то как раз и нету! И контейнер твой нахуй сломается при старте.

И да, если приложению вдруг понадобится что-то прочитать из файла или, не дай бог, TLS-сертификаты — их тоже надо явно в образ скопировать. Потому что там нихуя нет, даже корневых сертификатов, блядь.

Короче, инструмент для гиков, которые помешаны на размере и безопасности. Красиво, но без башенки не лезь — обосрёшься.