Выбор базового образа для контейнера определяет не только его размер, но и стабильность, скорость обновлений и совместимость со старым кодом. Alpine и Debian — два самых популярных варианта, но они решают разные задачи.

Ключевые различия

ПараметрAlpine LinuxDebian
Базовый размер образа~5 МБ~120 МБ
libcmuslglibc
Пакетный менеджерapkapt
Цикл обновленийRolling (постоянный)Stable (2 года)
Поддержка legacyСлабаяОтличная
Поверхность атакиМинимальнаяШирокая (но контролируемая)

Когда выбирать Alpine

Alpine — это дистрибутив, заточенный под безопасность и минимализм. Его основное преимущество — размер. Образ на 5 МБ стартует за доли секунды и занимает на диске в десятки раз меньше места, чем Debian-аналог.

Выбирайте Alpine, если:

  • Развёртываете микросервисы, где важен масштаб (сотни контейнеров на одном хосте)
  • Приложение на Go, Rust или статически скомпилированном C — без внешних зависимостей от glibc
  • Нужен максимально быстрый CI/CD — меньше образ, быстрее pull
  • Фронтенд-сборщики (Nginx с HTML, Node.js для сборки статики)

Подводный камень musl. Некоторые приложения, скомпилированные под glibc, ведут себя непредсказуемо в Alpine. Я видел случаи, когда Python-приложение с нативными модулями (numpy, pandas) падало с segfault при сборке в Alpine, хотя локально на Debian работало стабильно. Решение — либо пересобирать зависимости под musl, либо отказаться от Alpine.

Когда выбирать Debian

Debian — это стабильность и предсказуемость. Если Alpine — это гоночный болид, то Debian — грузовик: тяжелее, но везёт всё.

Выбирайте Debian, если:

  • Контейнеризуете legacy-приложение на PHP 5.6, Python 2.7 или старом Node.js
  • Нужны проприетарные библиотеки, собранные только под glibc (1С-коннекторы, некоторые SDK)
  • Важен долгосрочный LTS: Debian Stable получает обновления безопасности 5 лет
  • Команда не готова разбираться с musl-специфичными багами

Мой реальный кейс. Клиенту нужно было контейнеризовать ERP на PHP 5.6. В Alpine PHP 5.6 давно выпилен из репозиториев, а в Debian 11 он есть в виде стороннего репозитория. Собрали контейнер на Debian, ограничили поверхность атаки — убрали всё лишнее через multi-stage build. Итог: образ 180 МБ вместо 5 МБ Alpine, но приложение работает без переделок.

Практический подход: multi-stage build

Необязательно выбирать одно на всё. Для сборки используйте Debian (где есть все инструменты), а в финальный образ копируйте бинарник в Alpine или scratch:

# Этап сборки
FROM debian:12 AS builder
RUN apt-get update && apt-get install -y build-essential
COPY . /app
RUN make /app

# Финальный образ
FROM alpine:latest
COPY --from=builder /app/bin/myapp /usr/local/bin/
ENTRYPOINT ["myapp"]

Так вы получаете совместимость на этапе сборки и минимальный размер в production.

Rootless-контейнеры и systemd Quadlet

Если вы используете Podman (а я рекомендую), разница между Alpine и Debian в плане безопасности сглаживается. Podman и так запускает контейнеры без root, так что поверхность атаки уже ограничена. В этом случае выбор дистрибутива можно делать исходя из совместимости, а не из страха перед уязвимостями.

Итог

  • Alpine — для новых проектов, микросервисов, статической сборки и когда размер критичен.
  • Debian — для legacy, сложных зависимостей и когда важнее стабильность, чем мегабайты.
  • Multi-stage — чтобы совместить совместимость и размер.

Если не уверены, с чего начать — начните с Debian. Проще отладить, проще найти информацию, проще нанять человека, который разберётся. Переход на Alpine можно сделать позже, когда поймёте, что именно тормозит.

Нужна помощь с выбором инфраструктуры под ваш проект — от консультации до настройки контейнеров в Podman? Пишите, подберём оптимальный стек.

Готовы обсудить проект?

Опишите задачу — я оценю масштаб и предложу решение.

Обсудить проект →