Ответ
Да, установка зависимостей внутри контейнера — это стандартная и рекомендуемая практика. Она обеспечивает изоляцию среды, воспроизводимость сборки и независимость от хостовой системы.
Правильный подход через Dockerfile:
FROM python:3.9-slim
# Копируем файл зависимостей отдельно для кэширования слоя
COPY requirements.txt /tmp/
RUN pip install --no-cache-dir -r /tmp/requirements.txt
# Затем копируем остальной код приложения
COPY . /app
WORKDIR /app
Ключевые принципы:
- Фиксация версий: В
requirements.txtдолжны быть зафиксированы конкретные версии пакетов (например,Django==4.2.0). - Кэширование слоев: Отдельное копирование
requirements.txtи выполнениеRUN pip installдо копирования всего кода позволяет Docker кэшировать слой с зависимостями. Это значительно ускоряет последующие сборки, если зависимости не менялись. - Многоэтапная сборка (Multi-stage): Для production-образов используйте multi-stage builds, чтобы уменьшить итоговый размер образа, оставив в финальном образе только необходимые артефакты и зависимости времени выполнения.
Пример requirements.txt для воспроизводимости:
Django==4.2.0
djangorestframework==3.14.0
psycopg2-binary==2.9.6 Ответ 18+ 🔞
А, ну это же классика, ёпта! Сейчас объясню, как тут всё устроено, чтобы потом не орать «какого хуя?» на проде.
Смотри, если ты копируешь зависимости с хоста в контейнер через -v, то это пиздец какой распиздяйский подход. Представь: у тебя на локальной машине стоит Django 4.2, а в продакшене — 3.2. Контейнер возьмёт твои локальные пакеты, запустится, а потом начнёт сыпаться ошибками, потому что API поменялось. И ты будешь сидеть и чесать репу: «Ну я же на своей машине всё проверил, ёб твою мать!». А потому что доверия к такой схеме — ноль ебать.
Правильный путь — делать всё внутри Dockerfile, вот так:
FROM python:3.9-slim
# Сначала тащим файлик с зависимостями — это для хитрого кэширования
COPY requirements.txt /tmp/
RUN pip install --no-cache-dir -r /tmp/requirements.txt
# А уж потом весь наш код закидываем
COPY . /app
WORKDIR /app
Почему это работает, как швейцарские часы:
- Версии — святое. В
requirements.txtты пишешь чётко:Django==4.2.0, а не простоDjango. Иначе сегодня соберётся с одной версией, а завтра — уже с другой, и будет тебе хиросима. Пизда рулю твоему продакшену. - Кэш слоёв — твой лучший друг. Докер умный, он смотрит: ага,
requirements.txtне менялся с прошлой сборки. Значит, можно не качать и не ставить все эти пакеты заново, а взять готовый слой из кэша. Экономия времени — овердохуища. Если же скопировать весь код сразу, то любое изменение в нём заставит переустанавливать зависимости каждый раз. Зачем тебе этот мазохизм? - Multi-stage для прода — это айс. Если хочешь, чтобы образ весил не как хуй с горы, а компактно, гугли «multi-stage build». Суть в том, что в одном контейнере ты всё собираешь и компилируешь, а в финальный образ копируешь только готовые артефакты и рантайм-зависимости. Итоговый образ — легковесный и безопасный.
Вот как должен выглядеть твой requirements.txt, чтобы не было сюрпризов:
Django==4.2.0
djangorestframework==3.14.0
psycopg2-binary==2.9.6
Короче, запомни: зависимости живут внутри образа, а не примазываются к нему сбоку. Собрал образ — и он самодостаточный кусок железа, который будет работать везде одинаково. Иначе это не контейнеризация, а одна большая мудя.