Комментарии 30
First «the Dockerfiles in this article are not examples of best practices»
Well, that's a big mistake. Of course if you don't follow best practices you won't get the best results. In these examples the author doesn't even follow the basic recommendations from the Docker Alpine image page. Ex, use «apk add --no-cache PACKAGE». When you're caching apt & apk, of course the image is going to be a ton larger. On the flip side he does basically exactly that to clean up ubuntus apt cache.
The real article should have been «should you use alpine for every python/docker project?» and the answer is «No». If you're doing something complicated that requires a lot of system libs, like say machine learning or imagine manipulation — don't use Alpine. It's a pain. On the flip side if all you need is a small flask app, Alpine is a great solution.
Потому — multi-stage с python:3 и python:3-slim будут лучшим доступным решением.
ИМХО: Батарейки — главное преимущество Python, и главный его недостаток.
Alpine не поддерживает wheels
Он поддерживает wheels, это manylinux1 не поддерживается.
ну это не новость, что из-за musl в Alpine может быть много проблем.
Большой привет некоторым программистам на Си, беззаботно пихающим зависимости от glibc и т.п. в свои проекты, даже когда им вполне хватило бы POSIX.
Просто потому что задолбаешься выяснять как поставить какие-то библиотеки для него, а лишние 50 Мб роли особо не играют.
Вместо
RUN apk --update add gcc build-base
Лучше использовать
RUN apk --no-cache add gcc build-base
И после установки зависимостей python можно удалить часть пакетов, не нужных в runtime.
Может будет лучше)
И после установки зависимостей python можно удалить часть пакетов, не нужных в runtime.Для этого, кстати, у apk есть удобная опция --virtual:
RUN apk add --no-cache --virtual .build-deps gcc freetype-dev libpng-dev openblas-dev \
&& ./configure \
&& make \
&& ... \
&& apk del .build-deps
Именно. Это тот самый комментарий, который показывает, что автор изначальной статьи просто не разобрался как в alpine устанавливать питоновские либы. PS. Использую alpine с python больше 3 лет, с правильным подходом проблем ни с чем нк возникает.
Для себя проблему решили переборкой всех зависимостей и PYPI-proxy.
Как мне кажется — проблема не в alpine, а в отсутствии платформо-зависимых пакетов для него. ИМХО.
Касательно времени сборки — да, верное замечание, что если бы были готовые бинари, то мы не "попадали" бы на время сборки. Кстати, время сборки отчасти можно победить путем сборки СВОЕГО базового образа из alpine + самые часто используемые и долго собираемые зависимости. А потом уже в самом проекте докидывать из requirements.txt все остальное. Датасайентисты и инженеры так и делают. Ну, и версии пакетов зафиксированы — это тоже благо
Глупость говорите. Единственное с чем согласен — эльпайн требует отдельного подхода. Но это точно нельзя назвать 'правильным'.
Я уж не говорю, когда занимаетесь ml — попробуйте тот же torch или tensorflow водрузить на эльпайн. А ещё весело, когда у тебя проект состоит из 20 образов, разработчики все собрали из чего попало — что из эльпайна, что из убунту. В результате получается, что если все образы привести к единой общей базе, то они и качаются быстрее, и суммарно меньше места занимают, чем если они собраны из разных базовых.
Проще мультистейджем, ей-Богу
Не смотря на некоторые недочёты в использовании apk и в целом использования, спасибо за этот перевод. Я как-то не задумывался, что, возможно, некоторые тормоза и непонятного происхождения ошибки могут быть из-за musl. Думаю это отличный повод для исследования.
Одна из проблем, с которой мы столкнулись: https://github.com/jrottenberg/ffmpeg/issues/104
Было ОЧЕНЬ больно, т.к. это не бинарная история, что нечто либо работает, либо не работает, а ошибка проявлялась только при определенном наборе аргументов ffmpeg (facepalm)
Выше в комментариях уже отметили.
Вы хабр с лором не перепутали случаем? Что не так в статье кроме некоторых формулировок? wheels есть, собранные с musl? Нет. Ну вот и всё. Восьмиклассник он или нет, роли не играет, если вам нужен какой-нибудь SciPy, вы его задолбётесь собирать со всеми этими openblas/atlas/fortran как по времени так и по всяким траблам, которые могут внезапно вылезти.
Проект manylinux стал прорывом в своё время, он сильно облегчил жизнь людям, использующим Python-пакеты с C-extensions. Не стоит это недооценивать.
Я похожую статью писал в июле 2018 года:
Так ли мал Alpine 3.8 Docker для Python 3 runtime
https://habr.com/ru/post/415513/
Но это если у вас не слишком много разной тяжести в духе pandas'а и т.п.
Я использую вот такое для вебсервиса на sanic, в котором используются допом aiohttp, asyncpg, honeybadger, Jinja2, Pillow. Если pillow не нужен, то, например, jpeg-dev будет не нужен, контейнер будет меньше.
FROM python:3.7.5-alpine3.10 as base
FROM base as builder
RUN mkdir /install
WORKDIR /install
RUN apk add --no-cache python3-dev \
build-base \
libc6-compat \
libffi-dev \
zlib-dev \
jpeg-dev \
linux-headers
RUN pip3 install --upgrade pip
COPY requirements.txt ./
RUN pip3 install --prefix=/install -r requirements.txt
FROM base
RUN apk add --no-cache bash jpeg-dev && \
rm -r /tmp
EXPOSE 80
WORKDIR my_awesome_app
COPY --from=builder /install /usr/local
COPY my_awesome_app ./
RUN pip3 freeze
CMD ["python3", "app.py"]
Продакшн-контейнер получается 160MB.
Собрать мой стек на ubuntu/debian за быстро не получилось, поэтому, увы, без сравнения.
Двухшаговая сборка всё равно выглядит как какой-то dirty hack. В идеале помимо multi-stage build должна существовать система, в которой строятся параллельно два связанных образа: билд-образ и prod-образ. На prod-образе не должно быть ни package manager'а и всех его метаданных по установленным пакетам, ни даже busybox'а (если речь про alpine), если нам не нужен busybox. В принципе по минимуму это должен быть один лишь musl и нужное приложение (если оно больше ничего за собой не тянет). В минимальном же образе alpine 14 пакетов, большая часть которых нужна для apk.
Если пропустить все уже вышеназванное, то скорость создания образа можно вернуть установкой уже собранного пакета pandas.
apk add py3-pandas@testing py3-matplotlib@testing
Проверьте скорость собирания образа после этого :) Да, тестовая ведка означает что ваш пакет не проверяли полностью. В лучшем случае в нем есть юниттесты которые проверяют стандартно работоспособность библиотеки, в худшем вы можете иметь пакет который собран наобум. Все от случая к случаю, но если вы здесь, скорее всего вы маленькая часть пользователей Alpine которые имеют очень специфичные требования что не нужны для 90% другой аудиенции of Alpine.
В чем проблема? Видимо в том что разработчики pandas поналепили туда хаос зависимостей, которые в свою очередь имеют тоже тучу зависимостей, которые… И так несколько уровней. Огромное количество зависимостей понятное дело используют стандартный C, не musl, и требуют отдельной компиляции. Alpine сообщество разработчиков в целом решило не гадить своими "колесами" основной репозиторий pypi, и вместо этого просто компилит и пакует свои питоновые пакеты (в том числе pandas который из-за своего количества зависимостей занимает 1 час компиляции). Хорошо ли это, когда колеса не постятся "как обычно"? Наверно не очень для тех кто только в питоне разбирается, а в Alpine нет.
Однако самая большая вещь которая упускается здесь это то, что Alpine по своей сущности в основном для кручения на маломощном hardware или для контейнеров чтобы понизить footprint в безопасности (много программ = много дыр), и в ресурсоемкости (если последовать всем вышесказанным рекомендациям, образ будет в два раза меньше все равно) + меньше потребление памяти/CPU т.к. меньше фигни добавлено которая всегда идет с чем-то новоустановленным.
Привет из 2024!
Попалась на глаза заметка, и я, из любопытства повторил эксперимент с более свежими образами.
И вот что хочу по этому поводу отметить:
Ubuntu 22.04 (LTS) vs alpine 3.19, скорость сборки примерно одинакова(23 сек vs 18 сек), размер 214MB (ubuntu-gcc) vs 154MB (alpine-gcc)
в alpine 3.19 pip качает
.whl
размеры финальных образов: 356MB (python-slim) vs 279MB (python-alpine), время сборки 27 сек у slim и 32 сек у alpine
Alpine собирает Docker билды под Python в 50 раз медленней, а образы в 2 раза тяжелей