Spaces:
Running
Running
| # Multi-stage build for better reliability | |
| FROM node:22-bookworm-slim as base | |
| # Install system dependencies in a single layer to reduce image size | |
| RUN apt-get update && apt-get install -y \ | |
| libnss3 \ | |
| libdbus-1-3 \ | |
| libatk1.0-0 \ | |
| libgbm-dev \ | |
| libasound2 \ | |
| libxrandr2 \ | |
| libxkbcommon-dev \ | |
| libxfixes3 \ | |
| libxcomposite1 \ | |
| libxdamage1 \ | |
| libatk-bridge2.0-0 \ | |
| libpango-1.0-0 \ | |
| libcairo2 \ | |
| libcups2 \ | |
| bash \ | |
| git git-lfs \ | |
| wget curl procps \ | |
| htop vim nano \ | |
| xz-utils \ | |
| xvfb x11-utils \ | |
| nginx \ | |
| ca-certificates \ | |
| && rm -rf /var/lib/apt/lists/* \ | |
| && apt-get clean | |
| # Install FFmpeg 8 from static build with error handling | |
| RUN set -e && \ | |
| wget --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 -t 3 \ | |
| https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && \ | |
| tar -xf ffmpeg-release-amd64-static.tar.xz && \ | |
| mv ffmpeg-*-amd64-static/ffmpeg /usr/local/bin/ffmpeg && \ | |
| mv ffmpeg-*-amd64-static/ffprobe /usr/local/bin/ffprobe && \ | |
| chmod +x /usr/local/bin/ffmpeg /usr/local/bin/ffprobe && \ | |
| rm -rf ffmpeg-* && \ | |
| ln -sf /usr/local/bin/ffmpeg /usr/bin/ffmpeg && \ | |
| ln -sf /usr/local/bin/ffprobe /usr/bin/ffprobe && \ | |
| ffmpeg -version | |
| # Common-utils build stage - build the local common-utils dependency | |
| FROM base as common-utils-builder | |
| RUN mkdir /app && chown 1000 /app | |
| USER 1000 | |
| WORKDIR /app | |
| # Copy common-utils source and package files | |
| COPY --chown=1000 common-utils/ ./common-utils/ | |
| # Install TypeScript globally for building common-utils | |
| USER root | |
| RUN npm install -g typescript | |
| USER 1000 | |
| # Build common-utils - install dependencies and compile | |
| WORKDIR /app/common-utils | |
| RUN npm install && \ | |
| npm run build && \ | |
| echo "Common-utils build completed successfully" | |
| # Dependencies stage - isolate dependency installation | |
| FROM base as dependencies | |
| RUN mkdir /app && chown 1000 /app | |
| USER 1000 | |
| WORKDIR /app | |
| # Copy package files and npm config first for better caching | |
| COPY --chown=1000 package*.json ./ | |
| COPY --chown=1000 .npmrc ./ | |
| # Copy built common-utils from the builder stage | |
| COPY --from=common-utils-builder --chown=1000 /app/common-utils ./common-utils | |
| # Set comprehensive npm configurations for reliability and speed | |
| RUN npm config set fetch-retry-mintimeout 20000 && \ | |
| npm config set fetch-retry-maxtimeout 120000 && \ | |
| npm config set fetch-retries 5 && \ | |
| npm config set fetch-timeout 600000 && \ | |
| npm config set registry https://registry.npmjs.org/ && \ | |
| npm config set audit false && \ | |
| npm config set fund false && \ | |
| npm config set update-notifier false | |
| # Environment variables to skip problematic binary downloads | |
| ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true | |
| ENV PUPPETEER_SKIP_DOWNLOAD=true | |
| ENV SKIP_FFMPEG_DOWNLOAD=true | |
| ENV SHARP_IGNORE_GLOBAL_LIBVIPS=1 | |
| ENV NODE_ENV=production | |
| ENV CI=true | |
| # Clear any existing npm cache to prevent corruption | |
| RUN npm cache clean --force | |
| # Install dependencies with multiple fallback strategies and comprehensive error handling | |
| # Note: NOT using --no-optional to allow esbuild platform-specific binaries to install | |
| # Skip preinstall script since we already built common-utils | |
| 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 postinstall scripts separately for better control and debugging | |
| # Skip the common-utils build in postinstall since we already have it built | |
| 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..." | |
| # Verify critical packages are installed | |
| 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 stage | |
| FROM base as final | |
| # Create app directory and set permissions | |
| RUN mkdir -p /app /app/public /app/out /app/frames /app/uploads && chown -R 1000:1000 /app | |
| # Copy installed dependencies from the dependencies stage | |
| 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 application code (node_modules excluded via .dockerignore) | |
| COPY --chown=1000 . ./ | |
| # Ensure proper permissions for writable directories | |
| USER root | |
| RUN chmod -R 777 /app/public /app/out /app/uploads /app/frames || true && \ | |
| chmod 777 /app/index.html || true && \ | |
| mkdir -p /tmp/client_body /tmp/proxy_temp /tmp/fastcgi_temp /tmp/uwsgi_temp /tmp/scgi_temp && \ | |
| chmod -R 777 /tmp && \ | |
| chmod -R 777 /var && \ | |
| chmod -R 777 /app/node_modules/.cache || true | |
| # Copy nginx config and start script | |
| COPY --chown=1000 nginx.conf /etc/nginx/nginx.conf | |
| COPY --chown=1000 start.sh /app/start.sh | |
| RUN chmod +x /app/start.sh | |
| # Ensure nginx runs as root | |
| RUN sed -i 's/^user .*;/user root;/' /etc/nginx/nginx.conf || true | |
| USER 1000 | |
| # Ensure remotion browser is properly set up (do this after all dependencies are ready) | |
| RUN echo "Setting up Remotion browser..." && \ | |
| npx remotion browser ensure 2>&1 | tee /tmp/remotion-browser.log || \ | |
| echo "Browser setup had issues, but continuing..." | |
| # Verify the installation | |
| RUN echo "Verifying installation..." && \ | |
| node -e "console.log('Final verification - Node:', process.version)" && \ | |
| npm list --depth=0 | head -10 || true | |
| # Set up environment for runtime | |
| ENV DISPLAY=:99 | |
| ENV NODE_ENV=production | |
| # Expose required ports | |
| EXPOSE 7860 3000 8083 | |
| # Health check | |
| HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ | |
| CMD curl -f http://localhost:8083/ || exit 1 | |
| # Start the application | |
| CMD ["sh", "/app/start.sh"] | |
| # Build and run commands: | |
| # docker build -f Dockerfile.build.multistage -t render-farm:latest . | |
| # docker run -p 8083:8083 -it --rm render-farm:latest | |
| # docker run -p 8083:8083 -it --rm --entrypoint /bin/sh render-farm:latest |