multistage-uv
Multi-stage сборка через uv. Используется в уроках 6.2 и 6.3.
Что демонстрирует
uvкопируется из официального образа одной инструкциейCOPY --from;- версия
uvзакреплена — тегlatestсделал бы сборку невоспроизводимой; - разделение установки на два шага: зависимости отдельно от проекта;
--lockedтребует актуальногоuv.lockи падает, если он расходится сpyproject.toml;- cache mount для
~/.cache/uvпереживает пересборку; - в финальном образе нет ни
uv, ни исходников — только.venv.
Первый запуск
Файл uv.lock не входит в репозиторий примера, потому что его содержимое зависит от момента генерации. Создайте его один раз:
make lock
Команда запускает uv lock в container — устанавливать uv на хост не требуется.
Затем:
make build
make run
Ожидается:
болт 120 420.00
гайка 240 420.00
шайба 500 200.00
---------------------------
ИТОГО 860 1040.00
Почему uv.lock не в комплекте
uv sync --locked намеренно падает, если lock-файл отсутствует или устарел относительно pyproject.toml. Это правильное поведение для production: сборка не должна молча взять другие версии.
В реальном проекте uv.lock коммитится в репозиторий — тогда make lock не нужен, и сборка полностью воспроизводима.
Проверки
Образ не содержит uv и исходников:
docker run --rm --entrypoint sh multistage-uv -c 'command -v uv || echo "uv отсутствует"'
docker run --rm --entrypoint sh multistage-uv -c 'ls /app/src 2>/dev/null || echo "исходников нет"'
Приложение работает не от root:
docker run --rm --entrypoint id multistage-uv -u
Сравнение с эквивалентной сборкой на pip:
make compare
размеры образов (DISK USAGE):
multistage-uv:pip 206MB
multistage-uv:latest 190MB
Измерено на Docker Engine 29.7.1 (2026-08-05). Это DISK USAGE; docker image inspect вернёт вчетверо меньший CONTENT SIZE — 45 MB и 48 MB соответственно (урок 3.4).
Эффект cache mount — измените версию pydantic в pyproject.toml, выполните make lock и пересоберите: пакеты не будут скачиваться заново.
Уборка
make clean
rm -f uv.lock