# Simplified build using official Node 22 slim and static ffmpeg FROM node:22-slim AS base # ----------------------------------------------------------------------------- # tools stage: install fonts and ffmpeg static binary # ----------------------------------------------------------------------------- FROM base AS tools USER root RUN apt-get update RUN apt-get update && apt-get install -y curl ca-certificates fonts-deva fonts-noto fonts-noto-cjk jq xz-utils RUN apt-get update && \ apt-get install -y fontconfig \ && rm -rf /var/lib/apt/lists/* RUN mkdir -p /usr/local/bin # fetch and download the latest linux64 ffmpeg (cached layer) RUN DOWNLOAD_URL=$(curl -sSL https://api.github.com/repos/BtbN/FFmpeg-Builds/releases/latest \ | jq -r '.assets[] | select(.name | test("linux64.*(gpl|lgpl).*tar.xz")) | .browser_download_url' \ | head -n1) && \ if [ -z "$DOWNLOAD_URL" ]; then echo "failed to determine ffmpeg download url"; exit 1; fi && \ echo "downloading ffmpeg from $DOWNLOAD_URL" && \ curl -L "$DOWNLOAD_URL" -o /tmp/ffmpeg.tar.xz # extract ffmpeg archive into /opt/ffmpeg RUN mkdir -p /opt/ffmpeg && \ tar -xJ -C /opt/ffmpeg --strip-components=1 -f /tmp/ffmpeg.tar.xz && \ rm /tmp/ffmpeg.tar.xz ENV PATH="/opt/ffmpeg/bin:$PATH" ENV LD_LIBRARY_PATH="/opt/ffmpeg/lib:$LD_LIBRARY_PATH" # create app directory owned by non-root user RUN mkdir -p /app && chown -R 1000:1000 /app USER 1000 WORKDIR /app # ----------------------------------------------------------------------------- # common-utils builder # ----------------------------------------------------------------------------- FROM tools AS common-utils-builder USER 1000 WORKDIR /app COPY --chown=1000 common-utils/ ./common-utils WORKDIR /app/common-utils RUN npm ci && npm run build && echo "Common-utils build completed successfully" # ----------------------------------------------------------------------------- # dependencies installation # ----------------------------------------------------------------------------- FROM tools AS dependencies USER 1000 WORKDIR /app COPY --chown=1000 package*.json ./ COPY --chown=1000 .npmrc ./ COPY --from=common-utils-builder --chown=1000 /app/common-utils ./common-utils ENV NODE_ENV=production ENV CI=true RUN npm cache clean --force RUN set -e && \ echo "Starting dependency installation..." && \ (timeout 900 npm ci --verbose --ignore-scripts --production=false 2>&1 | tee /tmp/npm-install.log) || \ (echo "First attempt failed, cleaning cache and retrying..." && \ npm cache clean --force && \ rm -rf node_modules package-lock.json && \ timeout 900 npm install --verbose --ignore-scripts --production=false 2>&1 | tee -a /tmp/npm-install.log) || \ (echo "Second attempt failed, trying with reduced concurrency..." && \ npm cache clean --force && \ rm -rf node_modules && \ timeout 1200 npm install --verbose --maxsockets 1 --production=false 2>&1 | tee -a /tmp/npm-install.log) RUN echo "Running postinstall scripts..." && \ echo "Skipping common-utils build in postinstall as it's already built" && \ node ffmpeg-fix.js 2>&1 | tee -a /tmp/postinstall.log || echo "ffmpeg-fix completed" && \ npm rebuild --verbose 2>&1 | tee -a /tmp/npm-rebuild.log || \ echo "Some rebuilds failed, but continuing..." RUN node -e "console.log('Node version:', process.version)" && \ node -e "require('react'); console.log('React OK')" && \ node -e "require('remotion'); console.log('Remotion OK')" && \ ls -la node_modules/.bin/ | head -20 # ----------------------------------------------------------------------------- # final production image # ----------------------------------------------------------------------------- FROM tools AS final RUN mkdir -p /app/public /app/out /app/frames /app/uploads && chown -R 1000:1000 /app COPY --from=dependencies --chown=1000 /app/node_modules ./app/node_modules COPY --from=dependencies --chown=1000 /app/package*.json ./app/ COPY --from=dependencies --chown=1000 /app/common-utils ./app/common-utils USER 1000 WORKDIR /app COPY --chown=1000 . ./ COPY --chown=1000 start.sh /app/start.sh RUN chmod +x /app/start.sh RUN npm i RUN echo "Verifying installation..." && \ node -e "console.log('Final verification - Node:', process.version)" && \ npm list --depth=0 | head -10 || true EXPOSE 7860 3000 8083 CMD ["sh", "/app/start.sh"] # build: docker build -f Dockerfile.build.lean -t semibit/render-farm:lean . # run : docker run -p 8083:8083 -it --rm semibit/render-farm:lean