# Pinned to the exact Python version Blender's own CMake requires for this # release (build_files/cmake/Modules/FindPythonLibsUnix.cmake, # _PYTHON_VERSION_SUPPORTED) - a floating `python` tag drifts to whatever # "latest" currently is, which stops matching once it moves past what an # older/LTS Blender release hard-pins (it has no matching apt package to # install after the fact, unlike a missing library). ARG python_version=3.13 FROM python:${python_version} AS b3dock # Setup all software version request ARG b3d_vs_major=5.2 ARG b3d_vs_minor=0 LABEL Author="stilobique" LABEL Title="Blender Docker for Unit Test" LABEL Maintainer="Aurelien Vaillant contact@aurelien-vaillant.net" ## 01. Start First stage to build blender # Install dependencies RUN apt-get update && apt-get install -y git git-lfs sudo # Get source code RUN git clone --depth 1 --branch v${b3d_vs_major}.${b3d_vs_minor} \ https://projects.blender.org/blender/blender.git /opt/blender # Start build # install_linux_packages.py (default, no --all) skips a handful of packages # that are only provided via the precompiled-libs bundle or via --all: # libepoxy-dev, Boost (all components), OpenImageIO. --all itself is not an # option here: it also checks its own apt catalog for a python3-dev matching # [3.11, 3.13[, which fails on Debian trixie regardless of which Python the # base image runs (that check queries apt's package catalog, not the actual # interpreter on PATH). Since `make update` below skips the precompiled # bundle on Linux by default, these are needed from apt regardless - install # them explicitly instead. RUN cd /opt/blender/build_files/build_environment && \ chmod a+x ./install_linux_packages.py && \ python install_linux_packages.py && \ apt-get install -y libepoxy-dev libboost-all-dev libopenimageio-dev libembree-dev libpugixml-dev && \ pip install numpy cython && \ cd /opt/blender && make update && make -j$(nproc) # Discover Blender's *actual* runtime shared-library needs from the compiled # binary itself (ldd), instead of guessing from install_linux_packages.py # (that script only covers build-time deps; libSM/libICE were never listed # there but the binary needs them at runtime). Every resolved .so is mapped # back to the apt package that owns it, so stage 02 can install exactly that. RUN ldd /opt/build_linux/bin/blender | tee /dev/stderr | grep 'not found' && \ (echo 'Unresolved libs in the build stage itself, investigate first' && exit 1) || true # `realpath` is required: /lib is a merged-usr symlink to /usr/lib, and dpkg's # file database is keyed on the canonical /usr/lib/... path (with the full # soname suffix, e.g. libX11.so.6.4.0) — querying the /lib/....so.6 symlink # path directly returns "no path found matching pattern". # These names are resolved against Debian (this stage's distro), but stage 02 # installs them on Ubuntu - the two occasionally disagree on a package name # for the same library, and not just cosmetically: Debian's `libjpeg62-turbo` # provides libjpeg.so.62, but Ubuntu's identically-ABI-sounding # `libjpeg-turbo8` actually provides a DIFFERENT soname (libjpeg.so.8) - # Ubuntu ships the old libjpeg.so.62 ABI as a separate `libjpeg62` package. # Debian's generic `libxml2` is Ubuntu's soname-suffixed `libxml2-16`. # Remap the known cases here rather than in stage 02. RUN ldd /opt/build_linux/bin/blender \ | awk '{print $3}' | grep '^/' | sort -u \ | xargs -r realpath | sort -u \ | xargs -r dpkg -S 2>/dev/null | cut -d: -f1 | tr ',' '\n' | sed 's/^ //' | sort -u \ | sed -e 's/^libjpeg62-turbo$/libjpeg62/' -e 's/^libxml2$/libxml2-16/' \ | tee /opt/build_linux/runtime_packages.txt ## 02. Build optimissed image ## Setup a Multistage optimisation FROM ubuntu:25.10 AS final # Re-declared: ARGs before the first FROM only apply to that FROM line, not # to instructions in later stages. ARG python_version=3.13 # Install exactly the runtime packages ldd found the compiled binary needs # (see the b3dock stage above) instead of guessing from Blender's build-time # package list. Ubuntu and Debian share package names for these core libs. COPY --from=b3dock /opt/build_linux/runtime_packages.txt /tmp/runtime_packages.txt RUN apt-get update && \ xargs -a /tmp/runtime_packages.txt apt-get install -y --no-install-recommends && \ rm -rf /tmp/runtime_packages.txt /var/lib/apt/lists/* # libpython.so isn't an apt package: the b3dock base image builds # Python from source into /usr/local, so ldd/dpkg-S (above) can never find an # owning package for it - Ubuntu's apt only ships whatever Python versions it # currently defaults to, which won't match an older/LTS Blender's pin. Copy # the .so Blender actually linked against directly from the build stage. COPY --from=b3dock /usr/local/lib/libpython${python_version}.so.1.0 /usr/local/lib/libpython${python_version}.so.1.0 RUN ldconfig RUN useradd -m -s /bin/bash bld USER bld COPY --from=b3dock /opt/build_linux/bin /opt/blender # ARG b3d_vs_major # ENV B3D_ADDON_PATH="/home/bld/.config/blender/${b3d_vs_major}/scripts/addons" # Working Directory setup WORKDIR /opt/blender