ARG base_image=ubuntu:jammy-20260210.1
ARG base_image_tag=jammy
# Build stage: install dev tools, node, pnpm and build the monorepo from source
FROM ${base_image} AS builder
ENV NODE_MAJOR=22
ENV TUNARR_BIND_ADDR=0.0.0.0
# System deps
RUN rm /var/lib/dpkg/info/libc-bin.* \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update --fix-missing \
&& apt-get install -y libc-bin ca-certificates curl gnupg unzip wget musl-dev \
&& rm -rf /var/lib/apt/lists/*
# Node.js via NodeSource
RUN mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \
| tee /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# Install pnpm via corepack
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN npm install -g corepack@latest \
&& corepack enable && corepack enable pnpm \
&& pnpm --version
# Symlinks for ffmpeg bindings (if needed by/node modules)
RUN ln -s /usr/local/bin/ffmpeg /usr/bin/ffmpeg \
&& ln -s /usr/local/bin/ffprobe /usr/bin/ffprobe
WORKDIR /tunarr
# Copy repo sources (monorepo layout)
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
COPY scripts ./scripts
COPY server/ ./server
COPY shared/ ./shared
COPY types ./types
COPY web ./web
COPY patches ./patches
COPY CHANGELOG.md CHANGELOG.md
# Install dependencies and build
RUN pnpm install --frozen-lockfile \
&& pnpm turbo clean \
&& NODE_OPTIONS=--max-old-space-size=32768 pnpm turbo bundle --filter=@tunarr/web \
&& pnpm turbo make-bin -- --target linux-x64 --no-include-version
# Minimal env for runtime inside the builder (to be copied to final image)
RUN mkdir -p /tunarr \
&& echo 'TUNARR_BIND_ADDR=0.0.0.0' > /tunarr/.env \
&& echo 'TUNARR_VERSION=local' >> /tunarr/.env \
&& echo 'TUNARR_BUILD=local' >> /tunarr/.env
# Prepare a staging area that the final image will copy from
RUN mkdir -p /tunarr/server/bin \
&& cp -r server/bin/* /tunarr/server/bin/ \
&& cp -r .env /tunarr/.env 2>/dev/null || true
# Final image will reuse the built binaries
FROM ${base_image} AS runtime
ARG base_image
WORKDIR /tunarr
# Copy built artifacts from builder
COPY --from=builder /tunarr/.env /tunarr/.env
COPY --from=builder /tunarr/server/bin /tunarr/server/bin
# Create convenient symlinks for the binaries
RUN mkdir -p /tunarr/bin \
&& ln -s /tunarr/server/bin/meilisearch-linux-x64 /tunarr/bin/meilisearch \
&& ln -s /tunarr/server/bin/tunarr-linux-x64 /tunarr/tunarr
EXPOSE 8000
EXPOSE 1900/udp
CMD ["/tunarr/tunarr"]
node_modules/ **/node_modules/ dist/ build/ coverage/ .git/ .gitignore .env .env.local .env.* *.log pnpm-lock.yaml README.md docs/ docs-assets/ design/ patches/ server/node_modules/ web/node_modules/ shared/node_modules/ types/node_modules/
- Base image: ARG base_image=ubuntu:jammy-20260210.1; ARG base_image_tag=jammy
- Stages: builder (FROM ${base_image}) and runtime (FROM ${base_image})
- Environment: NODE_MAJOR=22; TUNARR_BIND_ADDR=0.0.0.0
- System deps installed in builder: libc-bin, ca-certificates, curl, gnupg, unzip, wget, musl-dev
- Node.js via NodeSource: install nodejs for NODE_MAJOR=22
- PNPM setup: PNPM_HOME="/pnpm"; PATH includes /pnpm; npm install -g corepack@latest; corepack enable; corepack enable pnpm; pnpm --version
- FFmpeg bindings symlinks: ln -s /usr/local/bin/ffmpeg /usr/bin/ffmpeg; ln -s /usr/local/bin/ffprobe /usr/bin/ffprobe
- Working dir: /tunarr
- Repository inputs copied to builder:
- COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
- COPY scripts ./scripts
- COPY server/ ./server
- COPY shared/ ./shared
- COPY types ./types
- COPY web ./web
- COPY patches ./patches
- COPY CHANGELOG.md CHANGELOG.md
- Install/build in builder:
- pnpm install --frozen-lockfile
- pnpm turbo clean
- NODE_OPTIONS=--max-old-space-size=32768 pnpm turbo bundle --filter=@tunarr/web
- pnpm turbo make-bin -- --target linux-x64 --no-include-version
- Runtime env for build: /tunarr/.env with TUNARR_BIND_ADDR=0.0.0.0, TUNARR_VERSION=local, TUNARR_BUILD=local
- Staging for final image: /tunarr/server/bin populated from server/bin; copy .env if present
- Final image copies from builder:
- /tunarr/.env
- /tunarr/server/bin
- Runtime symlinks and paths:
- mkdir -p /tunarr/bin
- ln -s /tunarr/server/bin/meilisearch-linux-x64 /tunarr/bin/meilisearch
- ln -s /tunarr/server/bin/tunarr-linux-x64 /tunarr/tunarr
- Exposed: 8000 and 1900/udp
- Entrypoint: CMD ["/tunarr/tunarr"]Summary of Docker build error
- Exact errors (no explicit exit code shown in log)
- ERROR: failed to build: failed to solve: failed to compute cache key: failed to calculate checksum of ref dm0crafjnw8l43ifl6uhde0ck::x75alw3ru10wnsk1qxhgda6yj: "/patches": not found
- ERROR: failed to build: failed to solve: failed to compute cache key: failed to calculate checksum of ref dm0crafjnw8l43ifl6uhde0ck::x75alw3ru10wnsk1qxhgda6yj: "/pnpm-lock.yaml": not found
- Failing commands/steps
- [builder 14/18] COPY patches ./patches
- [builder 8/18] COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
- Missing files / files excluded
- /patches not found in build context
- /pnpm-lock.yaml not found in build context
- Warnings indicate these files are excluded by .dockerignore:
- CopyIgnoredFile: Attempting to Copy file "pnpm-lock.yaml" that is excluded by .dockerignore (line 42)
- CopyIgnoredFile: Attempting to Copy file "patches" that is excluded by .dockerignore (line 48)
- Version / base image information
- Base image: ubuntu:jammy-20260210.1 (sha256 digest included in the log)
Notes
- The failures are due to .dockerignore excluding patches and pnpm-lock.yaml, causing checksum/cache key calculation to fail when those paths are attempted to be copied. To fix: either include these files in the build context, remove them from .dockerignore, or adjust the Dockerfile to conditionally copy only when present.node_modules/ **/node_modules/ dist/ build/ coverage/ .git/ .gitignore .env .env.local .env.* *.log # Allow pnpm lockfile to be included for build context # pnpm-lock.yaml # Allow patches to be included for build context # patches/ server/node_modules/ web/node_modules/ shared/node_modules/ types/node_modules/
Concerns: Container runs as root; consider adding a non-root user for security in production., ffmpeg-related symlink stubs are created even if the binaries may not be present in final image; verify runtime dependencies for ffmpeg bindings., No HEALTHCHECK instruction is defined; adding a health check could improve reliability in orchestrated environments. Smoke [FAIL]: test -x /tunarr/tunarr && echo 'tunarr_executable Output: sh: 1: Syntax error: Unterminated quoted string Smoke [FAIL]: test -f /tunarr/.env && echo '.env_present Output: sh: 1: Syntax error: Unterminated quoted string Smoke [FAIL]: test -L /tunarr/bin/meilisearch && echo 'meilisearch_symlink_present Output: sh: 1: Syntax error: Unterminated quoted string
ARG base_image=ubuntu:jammy-20260210.1
ARG base_image_tag=jammy
# Build stage: install dev tools, node, pnpm and build the monorepo from source
FROM ${base_image} AS builder
ENV NODE_MAJOR=22
ENV TUNARR_BIND_ADDR=0.0.0.0
# System deps
RUN rm /var/lib/dpkg/info/libc-bin.* \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update --fix-missing \
&& apt-get install -y libc-bin ca-certificates curl gnupg unzip wget musl-dev \
&& rm -rf /var/lib/apt/lists/*
# Node.js via NodeSource
RUN mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \
| tee /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# Install pnpm via corepack
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN npm install -g corepack@latest \
&& corepack enable && corepack enable pnpm \
&& pnpm --version
# Symlinks for ffmpeg bindings (if needed by/node modules)
RUN ln -s /usr/local/bin/ffmpeg /usr/bin/ffmpeg \
&& ln -s /usr/local/bin/ffprobe /usr/bin/ffprobe
WORKDIR /tunarr
# Copy repo sources (monorepo layout)
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
COPY scripts ./scripts
COPY server/ ./server
COPY shared/ ./shared
COPY types ./types
COPY web ./web
COPY patches ./patches
COPY CHANGELOG.md CHANGELOG.md
# Install dependencies and build
RUN pnpm install --frozen-lockfile \
&& pnpm turbo clean \
&& NODE_OPTIONS=--max-old-space-size=32768 pnpm turbo bundle --filter=@tunarr/web \
&& pnpm turbo make-bin -- --target linux-x64 --no-include-version
# Minimal env for runtime inside the builder (to be copied to final image)
RUN mkdir -p /tunarr \
&& echo 'TUNARR_BIND_ADDR=0.0.0.0' > /tunarr/.env \
&& echo 'TUNARR_VERSION=local' >> /tunarr/.env \
&& echo 'TUNARR_BUILD=local' >> /tunarr/.env
# Prepare a staging area that the final image will copy from
RUN mkdir -p /tunarr/server/bin \
&& cp -r server/bin/* /tunarr/server/bin/ \
&& cp -r .env /tunarr/.env 2>/dev/null || true
# Final image will reuse the built binaries
FROM ${base_image} AS runtime
ARG base_image
WORKDIR /tunarr
# Copy built artifacts from builder
COPY --from=builder /tunarr/.env /tunarr/.env
COPY --from=builder /tunarr/server/bin /tunarr/server/bin
# Create convenient symlinks for the binaries
RUN mkdir -p /tunarr/bin \
&& ln -s /tunarr/server/bin/meilisearch-linux-x64 /tunarr/bin/meilisearch \
&& ln -s /tunarr/server/bin/tunarr-linux-x64 /tunarr/tunarr \
&& chmod +x /tunarr/server/bin/meilisearch-linux-x64 /tunarr/tunarr
EXPOSE 8000
EXPOSE 1900/udp
CMD ["/tunarr/tunarr"]
Smoke [FAIL]: test -x /tunarr/tunarr && echo 'tunarr executable OK Output: sh: 1: Syntax error: Unterminated quoted string Smoke [FAIL]: test -f /tunarr/.env && echo '.env present Output: sh: 1: Syntax error: Unterminated quoted string Smoke [FAIL]: test -x /tunarr/server/bin/tunarr-linux-x64 && echo 'tunarr binary present Output: sh: 1: Syntax error: Unterminated quoted string
ARG base_image=ubuntu:jammy-20260210.1
ARG base_image_tag=jammy
# Stage 1: build from source
FROM ${base_image} AS builder
ENV NODE_MAJOR=22
ENV TUNARR_BIND_ADDR=0.0.0.0
RUN rm /var/lib/dpkg/info/libc-bin.* \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update --fix-missing \
&& apt-get install -y libc-bin ca-certificates curl gnupg unzip wget musl-dev \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js from NodeSource
RUN mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \
| tee /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# PNPM setup
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN npm install -g corepack@latest \
&& corepack enable && corepack enable pnpm \
&& pnpm --version
WORKDIR /tunarr
# Copy repo sources (monorepo layout)
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
COPY scripts ./scripts
COPY server/ ./server
COPY shared/ ./shared
COPY types ./types
COPY web ./web
COPY patches ./patches
COPY CHANGELOG.md CHANGELOG.md
RUN pnpm install --frozen-lockfile \
&& pnpm turbo clean \
&& NODE_OPTIONS=--max-old-space-size=32768 pnpm turbo bundle --filter=@tunarr/web \
&& pnpm turbo make-bin -- --target linux-x64 --no-include-version
# Create a minimal env for runtime
RUN mkdir -p /tunarr
RUN echo 'TUNARR_BIND_ADDR=0.0.0.0' > /tunarr/.env \
&& echo 'TUNARR_VERSION=local' >> /tunarr/.env \
&& echo 'TUNARR_BUILD=local' >> /tunarr/.env
# Copy built binaries to /tunarr/server/bin in this stage for final image
RUN mkdir -p /tunarr/server/bin \
&& cp -r server/bin/* /tunarr/server/bin/
# Stage 2: runtime image
FROM ${base_image} AS runtime
ARG base_image
WORKDIR /tunarr
# Copy binaries and env from builder
COPY --from=builder /tunarr/server/bin /tunarr/server/bin
COPY --from=builder /tunarr/.env /tunarr/.env
# Expose ports
EXPOSE 8000
EXPOSE 1900/udp
# Symlink tunarr into /tunarr for convenience
RUN mkdir -p /tunarr/bin \
&& ln -s /tunarr/server/bin/tunarr-linux-x64 /tunarr/tunarr
CMD ["/tunarr/tunarr"]
- VerifyBuild status: build_failed
- Concerns
- Potential brittle removal of libc-bin info: rm /var/lib/dpkg/info/libc-bin.* may fail if the glob doesn’t match (consider using rm -f)
- No explicit HEALTHCHECK; smoke tests rely on file presence but not runtime readiness (tunarr binary startup not verified beyond existence)
- Build error
- Exact error messages and exit code:
- cp: 'server/bin/meilisearch-linux-x64' and '/tunarr/server/bin/meilisearch-linux-x64' are the same file
- cp: 'server/bin/tunarr-linux-x64' and '/tunarr/server/bin/tunarr-linux-x64' are the same file
- Exit code: 1
- Failing command/step:
- Step: builder 18/18
- Dockerfile command: RUN mkdir -p /tunarr/server/bin && cp -r server/bin/* /tunarr/server/bin/
- Log lines:
- "RUN mkdir -p /tunarr/server/bin && cp -r server/bin/* /tunarr/server/bin/"
- "cp: 'server/bin/meilisearch-linux-x64' and '/tunarr/server/bin/meilisearch-linux-x64' are the same file"
- "cp: 'server/bin/tunarr-linux-x64' and '/tunarr/server/bin/tunarr-linux-x64' are the same file"
- Missing packages/files mentioned
- Not explicitly missing; the issue is a file-copy collision mapping two sources to the same destination inode:
- Duplicate: server/bin/meilisearch-linux-x64 and /tunarr/server/bin/meilisearch-linux-x64
- Duplicate: server/bin/tunarr-linux-x64 and /tunarr/server/bin/tunarr-linux-x64
- Version mismatch information
- None shown. The problem is a file-copy collision, not a version conflict.
- Notes / suggested fix
- Adjust COPY(cp) logic to avoid duplicating the same file under two paths (e.g., exclude duplicates or rename before copying)
- Summary (under 1500 chars)
Build failed due to cp colliding files when copying server/bin into /tunarr/server/bin: two sources map to the same destinations (meilisearch-linux-x64 and tunarr-linux-x64). Commands and paths involved:
- Dockerfile: RUN mkdir -p /tunarr/server/bin && cp -r server/bin/* /tunarr/server/bin/
- Errors:
- cp: 'server/bin/meilisearch-linux-x64' and '/tunarr/server/bin/meilisearch-linux-x64' are the same file
- cp: 'server/bin/tunarr-linux-x64' and '/tunarr/server/bin/tunarr-linux-x64' are the same file
- Exit code: 1
- Duplicates:
- server/bin/meilisearch-linux-x64 -> /tunarr/server/bin/meilisearch-linux-x64
- server/bin/tunarr-linux-x64 -> /tunarr/server/bin/tunarr-linux-x64
- No version mismatch reported; fix likely requires excluding duplicates or renaming before copy.ARG base_image=ubuntu:jammy-20260210.1
ARG base_image_tag=jammy
# Stage 1: build from source
FROM ${base_image} AS builder
ENV NODE_MAJOR=22
ENV TUNARR_BIND_ADDR=0.0.0.0
RUN rm /var/lib/dpkg/info/libc-bin.* \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update --fix-missing \
&& apt-get install -y libc-bin ca-certificates curl gnupg unzip wget musl-dev \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js from NodeSource
RUN mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \
| tee /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# PNPM setup
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN npm install -g corepack@latest \
&& corepack enable && corepack enable pnpm \
&& pnpm --version
WORKDIR /tunarr
# Copy repo sources (monorepo layout)
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
COPY scripts ./scripts
COPY server/ ./server
COPY shared/ ./shared
COPY types ./types
COPY web ./web
COPY patches ./patches
COPY CHANGELOG.md CHANGELOG.md
RUN pnpm install --frozen-lockfile \
&& pnpm turbo clean \
&& NODE_OPTIONS=--max-old-space-size=32768 pnpm turbo bundle --filter=@tunarr/web \
&& pnpm turbo make-bin -- --target linux-x64 --no-include-version
# Create a minimal env for runtime
RUN mkdir -p /tunarr
RUN echo 'TUNARR_BIND_ADDR=0.0.0.0' > /tunarr/.env \
&& echo 'TUNARR_VERSION=local' >> /tunarr/.env \
&& echo 'TUNARR_BUILD=local' >> /tunarr/.env
# Stage 2: runtime image
FROM ${base_image} AS runtime
ARG base_image
WORKDIR /tunarr
# Copy binaries and env from builder
COPY --from=builder /tunarr/server/bin /tunarr/server/bin
COPY --from=builder /tunarr/.env /tunarr/.env
# Expose ports
EXPOSE 8000
EXPOSE 1900/udp
# Symlink tunarr into /tunarr for convenience
RUN mkdir -p /tunarr/bin \
&& if [ -f /tunarr/server/bin/tunarr-linux-x64 ]; then ln -s /tunarr/server/bin/tunarr-linux-x64 /tunarr/tunarr; fi \
&& if [ -f /tunarr/server/bin/meilisearch-linux-x64 ]; then ln -s /tunarr/server/bin/meilisearch-linux-x64 /tunarr/bin/meilisearch; fi
CMD ["/tunarr/tunarr"]
Concerns: The build removes libc-bin dpkg info before apt operations; while common for size reduction, it could affect apt behavior on some base images., Build relies on network access to fetch NodeSource GPG key and Node.js packages; could fail in restricted environments., No healthcheck in runtime image; smoke tests do not verify runtime availability beyond file existence. Smoke [PASS]: test -f /tunarr/server/bin/tunarr-linux-x64 Smoke [PASS]: test -f /tunarr/.env && grep -q 'TUNARR_BIND_ADDR=0.0.0.0' /tunarr/.env Smoke [PASS]: test -L /tunarr/tunarr || test -f /tunarr/server/bin/tunarr-linux-x64