mysurik.ru

Почему я перевёл свои Docker контейнеры на Alpine Linux

Alpine Linux в Docker

С чего всё началось

У меня на сервере крутится около 20 Docker контейнеров. Каждый на Ubuntu или Debian. И каждый весит 200-400 MB. Я посчитал суммарный размер образов на диске — почти 8 гигабайт! Для террабайтного NVMe это копейки, но меня бесила неэффективность.

Начал смотреть, какие образы можно уменьшить. Нашёл Alpine Linux — дистрибутив на musl и busybox, который весит около 5 MB. Да, 5 мегабайт против 200 у Ubuntu.

Решил перевести все свои Dockerfile на Alpine.

С чем столкнулся

Первая проблема — musl вместо glibc. Многие программы собираются под glibc и на Alpine падают с ошибками. Например, npm-пакет sharp не собирался на Alpine, потому что требует glibc. Пришлось ставить libc6-compat через apk.

Вторая — пакетный менеджер apk. Я привык к apt, а apk работает иначе: команда не apt install python3, а apk add python3. Пришлось переписывать Dockerfile, привыкать. Но apk быстрее apt — это факт.

Третья — Node.js на Alpine официально поддерживается, но есть нюанс: версии в apk часто устаревшие. Лучше ставить Node через официальный образ node:alpine, а не через apk.

Python тоже норм. Стандартные библиотеки работают, но некоторые модули (например, mysqlclient) требуют компиляции, и на Alpine нужно ставить musl-dev и gcc.

Что я получил

Размер образов уменьшился в 5-10 раз. Мой nginx на Alpine весит 12 MB вместо 150 на Ubuntu. Python-сервисы — 50 MB вместо 300. PHP-FPM — 30 MB вместо 200.

Билды стали быстрее. apk качает пакеты быстрее apt. Сборка контейнера с нуля на Alpine занимает 30 секунд, на Ubuntu — 2-3 минуты.

Поверхность атаки меньше. Alpine минимален — в нём меньше потенциальных уязвимостей в стандартной поставке.

Мой первый Alpine контейнер

Помню, как собрал первый образ на Alpine для Python-скрипта, который парсит RSS и шлёт в Telegram. Раньше он жил в контейнере на Ubuntu — 280 MB. После переезда на Alpine стало 35 MB. Я обалдел. Перезапустил контейнер — стартанул за секунду. Раньше на Ubuntu грузился секунды 3-4. Разница вроде небольшая, но когда 20 контейнеров перезагружаются после обновления ядра — экономия времени ощутимая.

Что меня бесило в Alpine

Первое — отладка. В Alpine нет bash, только sh (busybox). Если привык к стрелочкам вверх и автодополнению — будешь страдать. Я ставлю bash через apk в dev-контейнерах, но в прод я его не тащу.

Второе — DNS. Alpine использует musl, у которого свои тараканы с резолвом. Была ситуация: контейнер на Alpine не мог достучаться до другого контейнера по hostname, пока я не прописал dns-сервер явно в docker-compose. На Ubuntu эта проблема не всплывала.

Третье — логи. По умолчанию в Alpine нет rsyslog или syslog-ng. Пришлось настраивать логгирование в stdout через Docker, чтобы логи попадали в docker logs. Мелочь, но кто первый раз ставит — теряет время.

Главный аргумент для перехода

Знаете, что меня окончательно убедило? Я обновил все образы на сервере, запустил docker system df и увидел: 8.2 GB стало 1.3 GB. Семь гигабайт свободного места на диске. Для домашнего сервера с NVMe на 256 GB — это серьёзно.

Плюс билды в CI/CD стали проходить за 40 секунд вместо 3 минут. Когда ты пушишь фикс и ждёшь деплой, каждая секунда на счету.

Я не фанатик. Если Alpine глючит с какой-то библиотекой — я не мучаюсь, беру Ubuntu. Но для 80% моих контейнеров Alpine — идеал. Маленький, быстрый, безопасный.

Кстати, я даже nginx собираю из сорцов на Alpine, а не беру готовый образ от nginx. Потому что официальный nginx:alpine — 11 MB, а nginx:latest — 187 MB. Разница в 17 раз. Задумайтесь.

Где я оставил Ubuntu

Не все контейнеры перевёл. Тяжёлые сервисы с кучей зависимостей (например, базы данных) оставил на Debian — там стабильнее поддержка драйверов. MySQL и PostgreSQL официально рекомендуют Debian. Для n8n оставил Ubuntu, потому что на нём проще отлаживать.

Но для простых сервисов типа nginx, Python-скриптов, PHP-FPM — только Alpine.

Совет

Если ваш контейнер делает что-то простое — проксирует запросы, выполняет Python-скрипты, отдаёт статику — переводите на Alpine. Сэкономите место, время сборки и нервы.

Если используете сложные библиотеки с нативными расширениями — сначала проверьте совместимость в тестовом контейнере. MySQL, Redis, PostgreSQL лучше не трогать.

Ваш комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *