Хотя технически возможно не использовать venv в контейнере, таком как Docker-образ, вам всё же, вероятно, захочется его применять.
Действительно минимальные образы встречаются крайне редко и стоят дорого. Если вы не уверены, что у вас именно такой образ, и не готовы поддерживать его в таком состоянии на протяжении всего проекта, независимо от того, кто будет над ним работать, лучше даже не пытаться.
В вашем образе, скорее всего, уже есть системные библиотеки Python. Установка зависимостей с root правами может привести к конфликтам с ними.
Вы не обязаны, но...
С учётом того, что контейнер по своей природе служит для изоляции, может показаться нелогичным добавлять ещё один слой изоляции поверх этого. Ведь основной смысл использования venv — избегать конфликтов между несколькими кодовыми базами или проектами, которые используют разные версии библиотек. В контейнере у вас всего одна кодовая база, так что, казалось бы, venv можно пропустить.
Во-первых, да, вы действительно можете обойтись без venv.
Существует множество программ, которые устанавливают зависимости прямо в корень контейнера, иногда даже с использованием sudo. И они работают. Как обычно, дело не в возможности или невозможности, а в ценности, которую вы получаете за свои усилия. С учётом того, насколько просты и недорогие venv, их использование в контейнере приносит действительно высокую отдачу.
Основная причина — однородность
Самая очевидная причина использовать venv — это обеспечение однородности: где бы вы ни находились, вы используете venv. Это избавляет вас от необходимости разбираться с вариациями и сложностями, которые они создают. У вас есть venv в небольшом прототипе, и когда он перемещается в свой собственный контейнер, venv остаётся с ним.
Вся документация имеет одинаковую ценность, независимо от проекта или контейнера, независимо от образа, как только вы находитесь в виртуальном окружении. Все действия приводят к одним и тем же последствиям. Это снижает когнитивную нагрузку: меньше нужно знать, меньше о чём нужно беспокоиться и меньше ошибок можно допустить.
Компании, которым удаётся достичь действительно однородного опыта в своей инфраструктуре и процессах разработки, встречаются крайне редко, даже с виртуализацией. Образы меняются, версии обновляются, настройки машин разработчиков различаются.
Кроме того, даже если вы работаете в такой редкой «компании-единороге», вам всё равно придётся работать в других контекстах, а другие люди придут из них к вам.
Поэтому основная причина использования venv схожа с принципом PEP 8: сообщество привыкло к этому, и это создаёт общий опыт.
И, снова повторим, venv настолько просты, что их применение почти ничего не стоит.
Насколько минимален ваш образ?
Шанс того, что вы действительно используете минималистичный образ для вашего контейнера, крайне низок. Потому что это невероятно сложно.
Это сложно сделать. И ещё сложнее поддерживать. Даже официальный Docker-образ Python содержит скомпилированный Python.
Для этого требуется огромное количество постоянно обновляющихся знаний о дистрибутиве, взаимодействиях различных пакетов в усложняющейся экосистеме, а также глубокое понимание зависимостей вашего стека и всех последствий их настройки.
Это всё равно что ожидать от владельца дома знаний о молекулярном составе материалов, из которых построен его дом. Да, какой-то крупный проект может себе это позволить, но обычные повседневные задачи — нет.
Это уровень требований к воспроизводимости и безопасности, как у Netflix.
Для обычного разработчика, однако, такие вещи, как библиотеки для работы с криптографией, сетевая инфраструктура или менеджер пакетов, работающий «из коробки», гораздо важнее, чем становиться полупрофессиональным сопровождающим Debian.
Ведь дело не только в нахождении идеальной комбинации минимальных зависимостей, которые подойдут вашему проекту. Дело ещё и в том, чтобы поддерживать эту конфигурацию на протяжении всего жизненного цикла проекта, независимо от того, сколько людей работает над ним.
К тому же, вы уверены, что полностью избавились от Python?
Потому что, как оказывается, множество системных пакетов написаны на Python: yum, dnf, do-release-upgrade, aptdcon, ubuntu-security-status... Даже если не учитывать всё это, рано или поздно вам захочется установить инструменты разработки в вашем образе, а они вполне могут быть написаны на Python. Потому что это популярный язык.
А если вы начнёте устанавливать пакеты через pip без venv, рано или поздно что-то из Pypi и что-то из операционной системы столкнутся. И им это не понравится. Это может случиться не сразу, а через несколько месяцев. И тогда вас ждёт огромный хаос с устранением проблем.
И снова появятся жалобы, что «упаковка в Python ужасна», хотя на самом деле проблема была в вашем подходе. Просто потому, что вы не захотели использовать однострочную команду для создания venv. Даже если риск этого конфликта составляет какие-то 0.00001%, он того не стоит.
По моему опыту, риск гораздо выше. Люди этого не осознают, потому что, столкнувшись с проблемой позже, они не связывают её с решением не использовать venv. Они винят язык или экосистему.
Но этой повреждённой библиотеки *.so, этого отсутствующего сертификата для GET-запроса или этого странного сбоя при импорте можно было полностью избежать — с помощью venv.
Мы говорим не о PHP, Ruby или JS: скорее всего, вы — не единственный пользователь Python на своей машине. Создатели дистрибутивов, на которых вы разворачиваетесь, тоже активно используют Python. Не смешивайте системные и пользовательские зависимости, чтобы избежать конфликтов — это всё равно что пересекать потоки, что всегда приводит к проблемам.
Но я осторожен!
Возможно.
И, возможно, вы по-настоящему компетентны.
Однако, по моему опыту, большинство разработчиков обладают средними навыками. Хотя, как и большинство водителей (и представителей других профессий), они считают себя выше среднего. Они либо переоценивают свои способности справляться с сложными системами, либо недооценивают их сложность. Они не знают того, чего не знают, и их вполне устраивает оставаться в этом неведении.
Но главное — они редко полностью несут ответственность за свои решения, касающиеся архитектуры. Они думают, что несут, но чаще всего это лишь сильное неудобство. Реальная цена распределяется между командой, компанией и пользователями.
Хорошо, допустим, это не про вас. Вы достаточно компетентны. Вы реалистичны. Вы осторожны.
А кто ещё работает над проектом сейчас? А будет работать через год?
Не путайте «работает на моей машине сейчас» с «будет работать через три месяца на проде после того, как стажёр что-то изменил, а OpenSSL выпустил обновление для устранения уязвимости нулевого дня».
Не говоря уже о том, сколько ресурсов вы готовы потратить на поддержание этого прекрасного чистого состояния установки без venv? На документацию? Обучение? Процессы?
Одна неправильная команда при изменении вашего образа — и вы можете добавить обратно системную зависимость Python, о которой вы даже не знали. Это невероятно легко испортить.
И ради чего? Какая цель? Если вы не можете ответить на этот вопрос мгновенно, просто используйте venv.
Конечно, есть веские причины пройти мимо venv. Но те, у кого они есть, уже о них знают. В этом нет философии, нет споров.
Например:
Вам нужен доступ к системным зависимостям из Python-кода, которые находятся в пакетах дистрибутива, но отсутствуют в Pypi, а параметр
--system-site-packages
вам не помог.Вы используете другой уровень изоляции, например, Buildout.
Вы сами компилируете всё, у вас полностью кастомная система с экзотическими правилами линковки, и вы хотите жёстко контролировать всё до мельчайших деталей.
Профессионал, которому нужно работать с таким уровнем кастомизации, не нуждается в этой статье. Он сам поймёт, что она ему не подходит.
Но…
«Я использую --user
!»
Вы всё равно рискуете столкнуться с проблемами с PATH
и теневыми зависимостями. Используйте venv.
«Я использую pyenv
!»
Это ортогональные инструменты. Используйте venv вместе с pyenv
.
«Это замедляет сборку моего образа!»
Время сборки образа, вероятно, не самая большая проблема по сравнению с другими аспектами, за исключением крайне редких случаев. Убедитесь, что ваш случай действительно из их числа.
Кроме того, если вы используете uv, сборка будет быстрее, чем установка на системном уровне.
Скоро у вас не останется выбора, поскольку основные дистрибутивы внедряют PEP 668. Это приведёт к тому, что установка через pip в системный Python по умолчанию завершится ошибкой и будет требовать использования виртуального окружения.
Системные разделяемые библиотеки становятся менее распространёнными, так как новые языки избегают их. Python не может легко удалить общую директорию пакетов из-за проблем с обратной совместимостью, но как сам Python, так и дистрибутивы всё активнее подталкивают пользователей к использованию изолированных окружений для каждого проекта, чтобы избежать конфликтов с системой. Это постепенно распространится и на базовые образы.
Другие убедительные причины использовать venv в контейнерах
Если избегания риска сломать ваш образ и ограничения сложности недостаточно, вот ещё несколько бонусов:
Список зависимостей вашего проекта в продакшене будет легко сравнить с тем, что используется в разработке. Или, если вы используете контейнер для разработки, с тем, что меняется при обновлении образов.
Нет необходимости в правах администратора, что может усложнить задачу злоумышленнику, пытающемуся проникнуть в ваш контейнер.
Вы можете легко использовать сторонние инструменты, такие как uv, poetry или anaconda, с настройками по умолчанию для установки зависимостей, вместо того чтобы пытаться принудительно устанавливать их на системном уровне.
Вы можете иметь несколько venv с разными версиями Python или библиотек, чтобы быстро тестировать обновления. Это гораздо легче, чем использовать несколько образов.
Вы можете хранить ваш venv в отдельном томе, что позволяет отделить зависимости Python от самого образа.
Всех, кому интересна тема автоматизации тестирования на Python, приглашаем на бесплатные открытые уроки:
Комментарии (4)
w00dLAN
23.01.2025 17:28Слог статьи создаёт ощущение Google translate или AI-generation.
MaxRokatansky
23.01.2025 17:28Подскажите, что навеяло мысли об участии AI? Возможно, нам стоит внимательнее присмотреться к источнику, хотя на первый взгляд он вызывает доверие. Ну а Google translate здесь точно не участвовал
c46fd3da
23.01.2025 17:28Статья из разряда вредных советов, все в точности наоборот
FROM python:3.12.2-slim as builder WORKDIR /app ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 RUN apt-get update && \ apt-get install -y --no-install-recommends gcc COPY requirements.txt . RUN pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements.txt # final stage FROM python:3.12.2-slim WORKDIR /app COPY --from=builder /app/wheels /wheels COPY --from=builder /app/requirements.txt . RUN pip install --no-cache /wheels/*
Verstov
Нет, не захочется