# ============================================ # SnapOtter - Test Dockerfile # Runs the full test suite (unit + integration) # ============================================ # ============================================ # Stage 1: Build libheif from source # ============================================ FROM node:22-bookworm@sha256:5647be709086c696ff32edaaf1c70cd26d1da6ab2b39c32f3c7b4c4a31957e37 AS libheif-builder ARG LIBHEIF_VERSION=1.23.1 ARG LIBDE265_VERSION=1.1.1 RUN apt-get update && apt-get install -y --no-install-recommends \ cmake pkg-config gcc g++ make curl ca-certificates \ libx265-dev libjpeg-dev libpng-dev \ && rm -rf /var/lib/apt/lists/* # Kept in step with docker/Dockerfile: the test image has to exercise the same # codec stack that ships, or the docker suite validates decoders we do not use. RUN curl --fail --location --silent --show-error --retry 3 \ --proto '=https' --tlsv1.2 \ --output /tmp/libde265.tar.gz \ "https://github.com/strukturag/libde265/releases/download/v${LIBDE265_VERSION}/libde265-${LIBDE265_VERSION}.tar.gz" \ && printf '%s %s\n' \ "fd48a927e94ed74fc7ce8829d222b9d8599fcbfe8b6448ba66705babc56ab219" \ /tmp/libde265.tar.gz | sha256sum --check --strict - \ && tar -xzf /tmp/libde265.tar.gz \ && cmake -B build-de265 -S "libde265-${LIBDE265_VERSION}" \ -DCMAKE_INSTALL_PREFIX=/opt/libheif \ -DBUILD_SHARED_LIBS=ON \ -DENABLE_SDL=OFF \ && cmake --build build-de265 -j$(nproc) \ && cmake --install build-de265 RUN curl --fail --location --silent --show-error --retry 3 \ --proto '=https' --tlsv1.2 \ --output /tmp/libheif.tar.gz \ "https://github.com/strukturag/libheif/releases/download/v${LIBHEIF_VERSION}/libheif-${LIBHEIF_VERSION}.tar.gz" \ && printf '%s %s\n' \ "0de0327f60fcd47de90d5654c6fe152232738d60d84fe084ec3e0f35e03b166a" \ /tmp/libheif.tar.gz | sha256sum --check --strict - \ && tar -xzf /tmp/libheif.tar.gz \ && PKG_CONFIG_PATH=/opt/libheif/lib/pkgconfig \ cmake -B build -S "libheif-${LIBHEIF_VERSION}" \ -DCMAKE_INSTALL_PREFIX=/opt/libheif \ -DCMAKE_PREFIX_PATH=/opt/libheif \ -DWITH_EXAMPLES=ON \ -DWITH_GDK_PIXBUF=OFF \ -DWITH_AOM_DECODER=OFF \ -DWITH_AOM_ENCODER=OFF \ -DWITH_DAV1D=OFF \ && cmake --build build -j$(nproc) \ && cmake --install build \ && test -e /opt/libheif/lib/libde265.so \ && readelf -d /opt/libheif/lib/libheif.so | grep -q 'NEEDED.*libde265' # ============================================ # Stage 2: Test runner # ============================================ FROM node:22-bookworm@sha256:5647be709086c696ff32edaaf1c70cd26d1da6ab2b39c32f3c7b4c4a31957e37 RUN corepack enable && corepack prepare pnpm@9.15.4 --activate RUN apt-get update && apt-get install -y --no-install-recommends \ libde265-0 \ libimage-exiftool-perl \ imagemagick \ libraw-dev \ libjxl-tools \ ghostscript \ qpdf \ tesseract-ocr \ tesseract-ocr-eng tesseract-ocr-deu tesseract-ocr-fra \ tesseract-ocr-spa tesseract-ocr-chi-sim tesseract-ocr-jpn \ && if apt-cache show libmagickcore-6.q16-7-extra >/dev/null 2>&1; then \ apt-get install -y --no-install-recommends libmagickcore-6.q16-7-extra; \ elif apt-cache show libmagickcore-6.q16-6-extra >/dev/null 2>&1; then \ apt-get install -y --no-install-recommends libmagickcore-6.q16-6-extra; \ else \ echo "No supported ImageMagick EXR coder package found" >&2; exit 1; \ fi \ && convert -list format | grep -Eq '^[[:space:]]*EXR([*[:space:]]|$)' \ && if apt-cache show libx265-199 >/dev/null 2>&1; then \ apt-get install -y --no-install-recommends libx265-199; \ elif apt-cache show libx265-209 >/dev/null 2>&1; then \ apt-get install -y --no-install-recommends libx265-209; \ fi \ && rm -rf /var/lib/apt/lists/* COPY --from=libheif-builder /opt/libheif/bin/ /usr/local/bin/ COPY --from=libheif-builder /opt/libheif/lib/ /usr/local/lib/ # The base image ships an older system libheif (~1.15) that shadows our built # 1.21 without this, so heif-dec fails with an undefined-symbol error. ENV LD_LIBRARY_PATH=/usr/local/lib RUN ldconfig # Allow ImageMagick's Ghostscript delegate to read EPS. Decoding an EPS goes # through the PostScript (PS) coder, so the default Debian policy.xml blocking # PS/PS2/PS3 must be opened too, not just EPS -- otherwise `convert` refuses with # a policy error before Ghostscript ever runs. RUN POLICY_FILE=$(find /etc/ImageMagick* -name policy.xml 2>/dev/null | head -1) && \ if [ -n "$POLICY_FILE" ]; then \ for CODER in EPS PS PS2 PS3; do \ sed -i "s/