# syntax=docker/dockerfile:1.7 # This Dockerfile uses cross-compilation to build for multiple architectures # efficiently without QEMU emulation overhead ###### node stage ###### # Use a pinned Node image instead of curl|bash installers. FROM --platform=$BUILDPLATFORM node:24.22.2-bookworm-slim AS node RUN npm install -g yarn@1.22.22 --force ###### mp4v2 stage ###### FROM --platform=$TARGETPLATFORM sandreas/mp4v2:2.1.1@sha256:c186cccc63b69a428be6a60359c29aff84bfacbd8597a4237038c7ccd7628a2d AS mp4v2 ###### deps stage ###### # Always build on the native architecture for speed FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0 AS deps WORKDIR /src # Copy Node + Yarn from the official Node image (avoids curl|bash installers). COPY --from=node /usr/local /usr/local # Copy only dependency manifests so cache is preserved when code changes COPY package.json yarn.lock ./ # Use BuildKit cache mount so tarballs stay on host between builds RUN --mount=type=cache,target=/root/.cache/yarn \ yarn install --frozen-lockfile ###### build stage ###### FROM --platform=$BUILDPLATFORM deps AS build WORKDIR /src # Bring in the rest of the project *after* deps are installed COPY . . # Front‑end build (architecture-independent) RUN yarn typecheck RUN yarn build # Build for the target architecture only. When building multi-platform images with Buildx, # Docker runs this Dockerfile once per target platform, so producing *all* arch outputs here # just bloats every final image layer. ARG TARGETPLATFORM RUN --mount=type=cache,target=/root/.nuget/packages,sharing=locked \ set -eux; \ case "$TARGETPLATFORM" in \ "linux/amd64") RUNTIME_ID="linux-x64" ;; \ "linux/arm64") RUNTIME_ID="linux-arm64" ;; \ "linux/arm/v7") RUNTIME_ID="linux-arm" ;; \ *) echo "Unsupported platform: $TARGETPLATFORM" && exit 1 ;; \ esac; \ dotnet restore src/Chaptarr.NoTests.sln -r "$RUNTIME_ID"; \ dotnet publish src/NzbDrone.Console/Chaptarr.Console.csproj -c Release -f net10.0 -r "$RUNTIME_ID" --self-contained false -o /app --no-restore /p:EnableWindowsTargeting=true /p:RunAnalyzersDuringBuild=false /p:RunCodeAnalysis=false /p:PublishSingleFile=false # Copy UI output to app directory RUN mkdir -p /app/UI && cp -r _output/UI/* /app/UI/ ###### runtime stage ###### # This stage runs on the target platform FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/aspnet:10.0 COPY build-tools/install-postgres-clients.sh /tmp/install-postgres-clients.sh # Install runtime dependencies (these are architecture-specific) RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends \ ffmpeg \ php-cli php-mbstring php-xml php-json php-curl php-zip \ wget \ gosu \ sqlite3 libsqlite3-0; \ sh /tmp/install-postgres-clients.sh; \ rm /tmp/install-postgres-clients.sh; \ rm -rf /var/lib/apt/lists/* # Copy pinned mp4v2 tools used by m4b-tool for chapter and tag writes. These # binaries are musl-linked, so keep their runtime libraries private. COPY --from=mp4v2 /usr/local/bin/mp4* /opt/mp4v2/bin/ COPY --from=mp4v2 /usr/local/lib/libmp4v2* /opt/mp4v2/lib/ COPY --from=mp4v2 /usr/lib/libstdc++.so.6* /usr/lib/libgcc_s.so.1 /opt/mp4v2/lib/ COPY --from=mp4v2 /lib/ld-musl-*.so.1 /lib/ COPY --from=mp4v2 /lib/ld-musl-*.so.1 /opt/mp4v2/lib/ COPY --from=mp4v2 /lib/libc.musl-*.so.1 /opt/mp4v2/lib/ RUN set -eux; \ for tool in /opt/mp4v2/bin/mp4*; do \ name="$(basename "$tool")"; \ printf '%s\n' \ '#!/bin/sh' \ 'export LD_LIBRARY_PATH="/opt/mp4v2/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"' \ "exec /opt/mp4v2/bin/${name} \"\$@\"" \ > "/usr/local/bin/${name}"; \ chmod +x "/usr/local/bin/${name}"; \ done; \ mp4info --version; \ mp4tags --version; \ mp4chaps --version # Download and install m4b-tool ARG M4B_TOOL_URL=https://github.com/sandreas/m4b-tool/releases/download/v0.5.2/m4b-tool.phar ARG M4B_TOOL_SHA256=a3ea9b81a4e8ce10ecc85c1fc712c982ba2622f2ed0318fb558dadfad4a590fa RUN set -eux; \ wget -O /usr/local/bin/m4b-tool "$M4B_TOOL_URL"; \ echo "${M4B_TOOL_SHA256} /usr/local/bin/m4b-tool" | sha256sum -c -; \ chmod +x /usr/local/bin/m4b-tool; \ php /usr/local/bin/m4b-tool --version # Copy our robust entrypoint script COPY docker-entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh WORKDIR /app COPY --from=build /app /app # Set app permissions at build time RUN chmod -R 755 /app EXPOSE 8789 ENTRYPOINT ["/entrypoint.sh"] CMD ["dotnet", "/app/Chaptarr.dll", "-nobrowser", "-data=/config"]