diff --git a/docker/Dockerfile b/docker/Dockerfile index 12c5ed4b5..19050ff8f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,115 +1,201 @@ -FROM ghcr.io/linuxserver/baseimage-ubuntu:noble AS builder +# ============================================================================ +# Stage 0: Common base, defined here like a constant for multiple subsequent stages +# ============================================================================ +FROM ghcr.io/linuxserver/baseimage-ubuntu:noble AS base -# version, it can be a TAG or a branch -ARG YACR_VERSION="develop" +# ============================================================================ +# Stage 1: build-base for all build steps +# ============================================================================ +FROM base AS plugin-base -# env variables ARG DEBIAN_FRONTEND="noninteractive" + +# Install common build packages used by all plugin builders +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + 7zip \ + build-essential \ + cmake \ + extra-cmake-modules \ + g++ \ + gcc \ + git \ + make \ + qt6-base-dev \ + qt6-base-private-dev \ + unzip \ + wget \ + pkg-config && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# ============================================================================ +# Stage 2: kimageformats builder +# ============================================================================ +FROM plugin-base AS kimageformats-builder + +# Install additional dependencies for kimageformats +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + libavif-dev \ + libjxl-dev \ + libarchive-dev && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Build ECM 6.0.0 for KF6 (compatible with Qt 6.4) +WORKDIR /tmp/ecm +RUN git clone --depth 1 --branch v6.0.0 https://invent.kde.org/frameworks/extra-cmake-modules.git . +RUN mkdir build +WORKDIR /tmp/ecm/build +RUN cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DBUILD_TESTING=OFF +RUN make -j$(nproc) +RUN make install + +# Build kimageformats 6.0.0 from KDE source (patched for Qt 6.4) +WORKDIR /tmp/kimageformats +RUN git clone --depth 1 --branch v6.0.0 https://invent.kde.org/frameworks/kimageformats.git . +# Patch to work with Qt 6.4 (Noble has 6.4.2, kimageformats wants 6.5+) +RUN sed -i 's/6\.5\.0/6.4.0/g' CMakeLists.txt +RUN mkdir build +WORKDIR /tmp/kimageformats/build +RUN cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DBUILD_TESTING=OFF \ + -DQT_MAJOR_VERSION=6 +RUN make -j$(nproc) +RUN make install DESTDIR=/output + +# ============================================================================ +# Stage 3: 7zip builder +# ============================================================================ +FROM plugin-base AS sevenzip-builder + +# Download 7z source +RUN mkdir -p /src/7zip +WORKDIR /src/7zip +RUN wget "https://github.com/YACReader/yacreader-7z-deps/blob/main/7z2301-src.7z?raw=true" -O 7z2301-src.7z + +# Extract 7z source +RUN 7z x 7z2301-src.7z -o/src/7zip/lib7zip && \ + rm 7z2301-src.7z + +# Build 7z.so with RAR support +WORKDIR /src/7zip/lib7zip/CPP/7zip/Bundles/Format7zF +RUN mkdir -p _o +RUN make -f makefile.gcc -j$(nproc) +RUN mkdir -p /app/lib/7zip && \ + cp ./_o/7z.so /app/lib/7zip + +# ============================================================================ +# Stage 4: YACReader builder +# ============================================================================ +FROM plugin-base AS yacreader-builder + +ARG YACR_VERSION="develop" ENV APPNAME="YACReaderLibraryServer" ENV HOME="/config" LABEL maintainer="luisangelsm" -# install build packages -RUN \ - apt-get update && \ +# Install YACReader-specific build packages (common packages inherited from plugin-base) +RUN apt-get update && \ apt-get install -y --no-install-recommends \ - build-essential \ - desktop-file-utils \ - gcc \ - g++ \ - git \ - qt6-tools-dev \ - qt6-base-dev-tools \ - qmake6 \ - qmake6-bin \ - qt6-base-dev \ - qt6-multimedia-dev \ - qt6-tools-dev-tools \ - libgl-dev \ - qt6-l10n-tools \ - libqt6opengl6-dev \ - libunarr-dev \ - qt6-declarative-dev \ - libqt6svg6-dev \ - libqt6core5compat6-dev \ - libbz2-dev \ - libglu1-mesa-dev \ - liblzma-dev \ - libqt6gui6 \ - libqt6multimedia6 \ - libqt6network6 \ - libqt6qml6 \ - libqt6quickcontrols2-6 \ - qt6-image-formats-plugins \ - libqt6sql6 \ - libqt6sql6-sqlite \ - make \ - sqlite3 \ - libsqlite3-dev \ - unzip \ - wget \ - 7zip \ - 7zip-rar \ - libpoppler-qt6-dev \ - zlib1g-dev && \ + desktop-file-utils \ + qt6-tools-dev \ + qt6-base-dev-tools \ + qmake6 \ + qmake6-bin \ + qt6-multimedia-dev \ + qt6-tools-dev-tools \ + libgl-dev \ + qt6-l10n-tools \ + libqt6opengl6-dev \ + libunarr-dev \ + qt6-declarative-dev \ + libqt6svg6-dev \ + libqt6core5compat6-dev \ + libbz2-dev \ + libglu1-mesa-dev \ + liblzma-dev \ + libqt6gui6 \ + libqt6multimedia6 \ + libqt6network6 \ + libqt6qml6 \ + libqt6quickcontrols2-6 \ + qt6-image-formats-plugins \ + libqt6sql6 \ + libqt6sql6-sqlite \ + sqlite3 \ + libsqlite3-dev \ + 7zip-rar \ + libpoppler-qt6-dev \ + zlib1g-dev && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* && \ ldconfig - -# clone YACReader repo +# Clone YACReader repository RUN git clone https://github.com/YACReader/yacreader.git /src/git && \ cd /src/git && \ git checkout $YACR_VERSION -# get 7zip source -RUN cd /src/git/compressed_archive && \ - wget "https://github.com/YACReader/yacreader-7z-deps/blob/main/7z2301-src.7z?raw=true" -O /src/git/compressed_archive/7z2301-src.7z && \ - 7z x /src/git/compressed_archive/7z2301-src.7z -o/src/git/compressed_archive/lib7zip +# Copy pre-built 7z library and headers +COPY --from=sevenzip-builder /src/7zip/lib7zip /src/git/compressed_archive/lib7zip +COPY --from=sevenzip-builder /app/lib/7zip /app/lib/7zip + +# Copy kimageformats Qt6 plugins +COPY --from=kimageformats-builder /output/usr/lib/x86_64-linux-gnu/qt6/plugins/imageformats/ \ + /usr/lib/x86_64-linux-gnu/qt6/plugins/imageformats/ -# build yacreaderlibraryserver +# Build YACReaderLibraryServer RUN cd /src/git/YACReaderLibraryServer && \ qmake6 PREFIX=/app CONFIG+="7zip server_standalone" YACReaderLibraryServer.pro && \ qmake6 -v && \ - make && \ + make -j$(nproc) && \ make install -# install 7z.so with RAR support -RUN echo "Building and installing 7z.so with RAR support..." && \ - cd "/src/git/compressed_archive/lib7zip/CPP/7zip/Bundles/Format7zF" && \ - make -f makefile.gcc && \ - mkdir -p /app/lib/7zip && \ - cp ./_o/7z.so /app/lib/7zip - -# Stage 2: Runtime stage -FROM ghcr.io/linuxserver/baseimage-ubuntu:noble +# ============================================================================ +# Stage 5: Final runtime image (minimal, no build assets) +# ============================================================================ +FROM base AS runtime -# env variables ENV APPNAME="YACReaderLibraryServer" ENV HOME="/config" +ENV LC_ALL="en_US.UTF-8" +ENV PATH="/app/bin:${PATH}" LABEL maintainer="luisangelsm" -# Copy the built application from the builder stage -COPY --from=builder /app /app - -# runtime packages +# Install only runtime dependencies (no build tools) RUN apt-get update && \ apt-get install -y --no-install-recommends \ - libqt6core5compat6 \ - libpoppler-qt6-3t64 \ - qt6-image-formats-plugins \ - libqt6network6t64 \ - libqt6sql6-sqlite && \ + libqt6core5compat6 \ + libpoppler-qt6-3t64 \ + qt6-image-formats-plugins \ + libavif16 \ + libjxl0.7 \ + libqt6network6t64 \ + libqt6sql6-sqlite && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -# set ENV -ENV LC_ALL="en_US.UTF-8" \ - PATH="/app/bin:${PATH}" +# Copy YACReaderLibraryServer application from builder +COPY --from=yacreader-builder /app /app + +# Copy kimageformats Qt6 plugins (must be done before ldconfig) +COPY --from=kimageformats-builder /output/usr/lib/x86_64-linux-gnu/qt6/plugins/imageformats/*.so \ + /usr/lib/x86_64-linux-gnu/qt6/plugins/imageformats/ + +# Refresh dynamic linker cache +RUN ldconfig -# copy files -COPY root.tar.gz / -# Extract the contents of root.tar.gz into the / directory -RUN tar -xvpzf /root.tar.gz -C / +# Copy linuxserver.io configuration +COPY docker/root.tar.gz / +RUN tar -xvpzf /root.tar.gz -C / && rm /root.tar.gz -# ports and volumes +# Expose server port and define volumes EXPOSE 8080 VOLUME ["/config", "/comics"] diff --git a/docker/TESTING.md b/docker/TESTING.md new file mode 100644 index 000000000..388fd82ae --- /dev/null +++ b/docker/TESTING.md @@ -0,0 +1,153 @@ +# Docker Image Format Testing Guide + +## Overview +This document describes how to test the kimageformats-based Docker image for YACReaderLibraryServer with AVIF and JXL support. + +## Prerequisites +- Docker installed +- Test comics with various image formats available at `/exos/comics/Mylar/_Incoming_Downloads/Format testing/` +- Files needed: `avif.cbz`, `jxl.cbz`, `test_combined.cbz` + +## Build the Image + +```bash +cd /home/nick/yacreader +docker build -f docker/Dockerfile -t yacreader-test:kimageformats . +``` + +Expected: Build completes successfully with 6 stages (base, plugin-base, kimageformats-builder, sevenzip-builder, yacreader-builder, runtime) + +## Copy Test Files + +```bash +mkdir -p /home/nick/yacreader/test-comics +cp "/exos/comics/Mylar/_Incoming_Downloads/Format testing/"*.cbz /home/nick/yacreader/test-comics/ +ls -la /home/nick/yacreader/test-comics/ +``` + +Expected: See avif.cbz, jxl.cbz, test_combined.cbz, test_heic.cbz, test_heif.cbz + +## Run Container + +```bash +docker rm -f YACReaderTest 2>/dev/null +docker run --rm -d \ + --name YACReaderTest \ + -p 8086:8080 \ + -v /home/nick/yacreader/test-comics:/comics \ + -e PUID=$(id -u) \ + -e PGID=$(id -g) \ + yacreader-test:kimageformats + +# Wait for startup +sleep 5 +``` + +## Verify Image Format Support + +```bash +docker logs YACReaderTest 2>&1 | grep "Image formats" +``` + +Expected output should include: +- `avif` ✅ +- `avifs` ✅ +- `jxl` ✅ +- Plus bonus formats: ani, hdr, pcx, psd, qoi, xcf, etc. + +**Should NOT include:** heic, heif (not supported in kimageformats 6.0.0) + +## Create and Scan Library + +```bash +# Create .yacreaderlibrary directory with correct permissions +docker exec -u abc YACReaderTest mkdir -p /comics/.yacreaderlibrary + +# Create library and scan comics +docker exec YACReaderTest YACReaderLibraryServer create-library "TestComics" /comics +``` + +Expected output: +``` +Processing comics...Done! +Number of comics processed = 3 +``` + +Note: Only 3 comics should be processed (avif.cbz, jxl.cbz, test_combined.cbz). The HEIC/HEIF files are skipped because format not supported. + +## Verify Comics via Web Interface + +```bash +curl -s http://localhost:8086/library/1/folder/1 | grep -i "comic" | head -15 +``` + +Expected: HTML output showing 3 comics with sizes and page counts + +## Check Specific Comic Details + +```bash +docker exec YACReaderTest ls -la /comics/.yacreaderlibrary/ +``` + +Expected: +- `library.ydb` (SQLite database) +- `covers/` directory +- `id` file + +## Verify Plugins Are Installed + +```bash +docker exec YACReaderTest ls -la /usr/lib/x86_64-linux-gnu/qt6/plugins/imageformats/ | grep kimg +``` + +Expected output should include: +- `kimg_avif.so` ✅ +- `kimg_jxl.so` ✅ +- Plus: kimg_ani.so, kimg_hdr.so, kimg_pcx.so, kimg_psd.so, kimg_qoi.so, kimg_xcf.so, etc. + +## Cleanup + +```bash +docker stop YACReaderTest +docker rm YACReaderTest 2>/dev/null +``` + +## Known Limitations + +1. **HEIC/HEIF not supported**: kimageformats 6.0.0 (compatible with Ubuntu Noble's Qt 6.4.2) doesn't include HEIC/HEIF plugins. Test files `test_heic.cbz` and `test_heif.cbz` will be skipped during library scan. + +2. **Compatibility patch required**: kimageformats 6.0.0 requires Qt 6.5+, but Ubuntu Noble has Qt 6.4.2. The Dockerfile includes a sed command to patch the version check: `sed -i 's/6\.5\.0/6.4.0/g' CMakeLists.txt` + +## Success Criteria + +- [x] Build completes without errors +- [x] Container starts and shows AVIF/JXL in supported formats +- [x] Library creation processes 3 comics successfully +- [x] Web interface shows all 3 comics +- [x] kimageformats plugins are installed in correct location +- [x] HEIC/HEIF files are gracefully skipped (not errors) + +## Comparison Test (Optional) + +Compare with the original PR #499 implementation: + +```bash +# Original (PR #499) +docker logs YACReaderLibraryServer 2>&1 | grep "Image formats" +# Should show: avif, avifs, heic, heif, jxl + +# New (kimageformats) +docker logs YACReaderTest 2>&1 | grep "Image formats" +# Should show: avif, avifs, jxl (+ 30+ bonus formats, no heic/heif) +``` + +## Troubleshooting + +**Problem:** "Unable to find database at: /comics/.yacreaderlibrary" +- **Solution:** Ensure .yacreaderlibrary directory exists with correct permissions. Use `create-library` instead of `add-library` + `update-library`. + +**Problem:** No comics scanned +- **Solution:** Check file permissions. Container runs as uid/gid 1000 (abc user). Files should be readable by this user. + +**Problem:** kimageformats plugins not found +- **Solution:** Verify COPY command in Dockerfile uses `*.so` wildcard and paths match build output structure.