2026, Jan 10 18:02

Как исправить ошибку pyproj в Docker: конфликт с Cython 3

Почему падает pip install в Docker (python:3.11-alpine) при сборке pyproj: конфликт с Cython 3.0+. Воспроизводим ошибку и даем фикс: Cython<3 и pyproj>=3.7.1.

Когда ранее стабильная сборка Docker внезапно падает на этапе pip install, первое желание — списать всё на базовый образ или странный сбой в цепочке сборки. В нашем случае сбой проявился на Python 3.11 с базой Alpine, а логи указывали на компиляцию pyproj с помощью Cython, заканчиваясь ошибкой: “Unsafe C derivative of temporary Python reference used in conditional expression”. В проекте ничего не меняли, пробовали старые версии — и всё равно падало. Источником проблемы оказалась несовместимость версий между Cython 3.0+ и старыми релизами pyproj.

Как воспроизвести сбой

Проблема проявлялась при сборке внутри образа python:3.11-alpine, где заранее установлены системные зависимости для геопространственных инструментов и PDAL. В такой конфигурации установка зависимостей пользовательского пакета, который транзитивно подтягивает pyproj (и другие геолибы), стабильно падала.

FROM python:3.11-alpine
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV PYTHONOPTIMIZE 2
ENV PIP_DISABLE_PIP_VERSION_CHECK 1
ENV PIP_EXTRA_INDEX_URL https://internal_gitlab_pypi_registry
ENV PIP_PROGRESS_BAR off
ENV PIP_RETRIES 1
ENV PIP_ROOT_USER_ACTION ignore
WORKDIR /workspace/app
RUN apk add --no-cache gcc musl-dev linux-headers python3-dev libstdc++ g++ geos-dev proj-dev proj-util
RUN apk add --no-cache gdal pdal-dev pdal
RUN pdal --version
RUN apk add --no-cache git cmake make
RUN git clone https://github.com/PDAL/wrench.git
RUN mkdir ./wrench/build
WORKDIR ./wrench/build
RUN cmake ..
RUN make
ENV PATH="/workspace/app/wrench/build:${PATH}"
WORKDIR /opt
RUN git clone --branch 1.4.0 --single-branch https://github.com/hobuinc/untwine.git
RUN mkdir /opt/untwine/build
WORKDIR /opt/untwine/build
RUN cmake ..
RUN make
ENV PATH="/opt/untwine/build/bin:${PATH}"
WORKDIR /workspace/app
RUN pip install -r reqs/base-gpf.txt

Вывод pip ясно показывал, где именно рушится сборка. Ключевым фрагментом была ошибка времени компиляции от Cython при сборке pyproj:

Unsafe C derivative of temporary Python reference used in conditional expression

Что на самом деле происходит

Сбой вызван ужесточённой проверкой типов в Cython версии 3.0+ при компиляции старых исходников pyproj. Именно это приводит к упомянутой выше ошибке и обрывает шаг “Getting requirements to build wheel” для pyproj. Это не баг pip, и откат версий ваших собственных пакетов не поможет, если pyproj всё ещё разрешается в старый релиз, конфликтующий с Cython 3.0+.

Надёжное решение

Практичный выход — обеспечить совместимую связку: зафиксировать Cython ниже 3.0.0 или перейти на более новый pyproj с поддержкой этой версии. Ещё лучше задать оба ограничения заранее, чтобы избежать неоднозначностей при разрешении зависимостей.

RUN pip install "Cython<3.0.0" "pyproj>=3.7.1"

Поместите эту строку перед установкой ваших требований, чтобы к моменту подтягивания pyproj в окружении уже был нужный инструментарий и подходящая версия зависимости. Dockerfile с исправленным порядком может выглядеть так:

FROM python:3.11-alpine
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV PYTHONOPTIMIZE 2
ENV PIP_DISABLE_PIP_VERSION_CHECK 1
ENV PIP_EXTRA_INDEX_URL https://internal_gitlab_pypi_registry
ENV PIP_PROGRESS_BAR off
ENV PIP_RETRIES 1
ENV PIP_ROOT_USER_ACTION ignore
WORKDIR /workspace/app
RUN apk add --no-cache gcc musl-dev linux-headers python3-dev libstdc++ g++ geos-dev proj-dev proj-util
RUN apk add --no-cache gdal pdal-dev pdal
RUN pdal --version
RUN apk add --no-cache git cmake make
RUN git clone https://github.com/PDAL/wrench.git
RUN mkdir ./wrench/build
WORKDIR ./wrench/build
RUN cmake ..
RUN make
ENV PATH="/workspace/app/wrench/build:${PATH}"
WORKDIR /opt
RUN git clone --branch 1.4.0 --single-branch https://github.com/hobuinc/untwine.git
RUN mkdir /opt/untwine/build
WORKDIR /opt/untwine/build
RUN cmake ..
RUN make
ENV PATH="/opt/untwine/build/bin:${PATH}"
WORKDIR /workspace/app
RUN pip install "Cython<3.0.0" "pyproj>=3.7.1"
RUN pip install -r reqs/base-gpf.txt

После этого pyproj либо возьмёт совместимое готовое колесо, либо соберётся без ошибок с зафиксированным Cython. На практике обычно достаточно обновить pyproj до 3.7.1.

Зачем это важно

Сборочные цепочки развиваются независимо от кода приложения. Транзитивная зависимость, собираемая Cython, может начать падать, даже если вы не меняли requirements, просто потому что в окружение попала новая версия Cython. Умение распознать истинный сигнал об ошибке — здесь это диагностика Cython об «unsafe C derivative» — помогает лечить первопричину, а не искать проблемы в сторонних местах.

Главное

Если сборка pip в Docker падает на pyproj с ошибкой “Unsafe C derivative of temporary Python reference used in conditional expression”, устраняйте несовместимость между Cython и pyproj. Установите заранее Cython<3.0.0 и потребуйте pyproj>=3.7.1 перед остальными зависимостями — так сборка стабилизируется. Следите за транзитивными зависимостями, которые компилируют расширения, и при разборе проблем выводите на первый план первую осмысленную ошибку из логов pip.