Sync: Optimised compose long context arguments. Gradio MCP can be installed conditionally in Dockerfile. Back to Gradio 6.10.0
e9989ec | # Stage 1: Build dependencies and download models | |
| FROM public.ecr.aws/docker/library/python:3.12.13-slim-trixie AS builder | |
| # Install system dependencies | |
| RUN apt-get update \ | |
| && apt-get upgrade -y \ | |
| && apt-get install -y --no-install-recommends \ | |
| g++ \ | |
| make \ | |
| cmake \ | |
| unzip \ | |
| libcurl4-openssl-dev \ | |
| git \ | |
| && pip install --upgrade pip \ | |
| && apt-get clean \ | |
| && rm -rf /var/lib/apt/lists/* | |
| WORKDIR /src | |
| COPY requirements_lightweight.txt . | |
| RUN pip install --verbose --no-cache-dir --target=/install -r requirements_lightweight.txt && rm requirements_lightweight.txt | |
| ARG INSTALL_GRADIO_MCP=False | |
| ENV INSTALL_GRADIO_MCP=${INSTALL_GRADIO_MCP} | |
| RUN if [ "$INSTALL_GRADIO_MCP" = "True" ]; then \ | |
| pip install --verbose --no-cache-dir --force-reinstall --target=/install "gradio[mcp]<=6.10.0"; \ | |
| fi | |
| # Optionally install PaddleOCR if the INSTALL_PADDLEOCR environment variable is set to True. Note that GPU-enabled PaddleOCR is unlikely to work in the same environment as a GPU-enabled version of PyTorch, so it is recommended to install PaddleOCR as a CPU-only version if you want to use GPU-enabled PyTorch. | |
| ARG INSTALL_PADDLEOCR=False | |
| ENV INSTALL_PADDLEOCR=${INSTALL_PADDLEOCR} | |
| ARG PADDLE_GPU_ENABLED=False | |
| ENV PADDLE_GPU_ENABLED=${PADDLE_GPU_ENABLED} | |
| RUN if [ "$INSTALL_PADDLEOCR" = "True" ] && [ "$PADDLE_GPU_ENABLED" = "False" ]; then \ | |
| pip install --verbose --no-cache-dir --target=/install "protobuf<=7.34.0" && \ | |
| pip install --verbose --no-cache-dir --target=/install "paddlepaddle<=3.2.1" && \ | |
| pip install --verbose --no-cache-dir --target=/install "paddleocr<=3.3.0"; \ | |
| elif [ "$INSTALL_PADDLEOCR" = "True" ] && [ "$PADDLE_GPU_ENABLED" = "True" ]; then \ | |
| pip install --verbose --no-cache-dir --target=/install "protobuf<=7.34.0" && \ | |
| pip install --verbose --no-cache-dir --target=/install "paddlepaddle-gpu<=3.2.1" --index-url https://www.paddlepaddle.org.cn/packages/stable/cu129/ && \ | |
| pip install --verbose --no-cache-dir --target=/install "paddleocr<=3.3.0"; \ | |
| fi | |
| ARG INSTALL_VLM=False | |
| ENV INSTALL_VLM=${INSTALL_VLM} | |
| ARG TORCH_GPU_ENABLED=False | |
| ENV TORCH_GPU_ENABLED=${TORCH_GPU_ENABLED} | |
| # Optionally install VLM/LLM packages if the INSTALL_VLM environment variable is set to True. | |
| RUN if [ "$INSTALL_VLM" = "True" ] && [ "$TORCH_GPU_ENABLED" = "False" ]; then \ | |
| pip install --verbose --no-cache-dir --target=/install \ | |
| "torch==2.9.1+cpu" \ | |
| "torchvision==0.24.1+cpu" \ | |
| "transformers<=5.5.4" \ | |
| "accelerate<=1.13.0" \ | |
| "bitsandbytes<=0.49.2" \ | |
| "sentencepiece<=0.2.1" \ | |
| --extra-index-url https://download.pytorch.org/whl/cpu; \ | |
| elif [ "$INSTALL_VLM" = "True" ] && [ "$TORCH_GPU_ENABLED" = "True" ]; then \ | |
| pip install --verbose --no-cache-dir --target=/install "torch<=2.8.0" --index-url https://download.pytorch.org/whl/cu129 && \ | |
| pip install --verbose --no-cache-dir --target=/install "torchvision<=0.23.0" --index-url https://download.pytorch.org/whl/cu129 && \ | |
| pip install --verbose --no-cache-dir --target=/install \ | |
| "transformers<=5.5.4" \ | |
| "accelerate<=1.13.0" \ | |
| "bitsandbytes<=0.49.2" \ | |
| "sentencepiece<=0.2.1" && \ | |
| pip install --verbose --no-cache-dir --target=/install "optimum<=2.1.0" && \ | |
| pip install --verbose --no-cache-dir --target=/install https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.8cxx11abiTRUE-cp312-cp312-linux_x86_64.whl && \ | |
| pip install --verbose --no-cache-dir --target=/install https://github.com/ModelCloud/GPTQModel/releases/download/v5.8.0/gptqmodel-5.8.0+cu128torch2.8-cp312-cp312-linux_x86_64.whl; \ | |
| fi | |
| # =================================================================== | |
| # Stage 2: A common base for both Lambda and Gradio | |
| # =================================================================== | |
| FROM public.ecr.aws/docker/library/python:3.12.13-slim-trixie AS base | |
| # MUST re-declare ARGs in every stage where they are used in RUN commands | |
| ARG TORCH_GPU_ENABLED=False | |
| ARG PADDLE_GPU_ENABLED=False | |
| ENV TORCH_GPU_ENABLED=${TORCH_GPU_ENABLED} | |
| ENV PADDLE_GPU_ENABLED=${PADDLE_GPU_ENABLED} | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| tesseract-ocr \ | |
| poppler-utils \ | |
| libgl1 \ | |
| libglib2.0-0 && \ | |
| if [ "$TORCH_GPU_ENABLED" = "True" ] || [ "$PADDLE_GPU_ENABLED" = "True" ]; then \ | |
| apt-get install -y --no-install-recommends libgomp1; \ | |
| fi && \ | |
| apt-get clean && rm -rf /var/lib/apt/lists/* | |
| ENV APP_HOME=/home/user | |
| # Set env variables for Gradio & other apps | |
| ENV GRADIO_TEMP_DIR=/tmp/gradio_tmp/ \ | |
| TLDEXTRACT_CACHE=/tmp/tld/ \ | |
| MPLCONFIGDIR=/tmp/matplotlib_cache/ \ | |
| GRADIO_OUTPUT_FOLDER=$APP_HOME/app/output/ \ | |
| GRADIO_INPUT_FOLDER=$APP_HOME/app/input/ \ | |
| FEEDBACK_LOGS_FOLDER=$APP_HOME/app/feedback/ \ | |
| ACCESS_LOGS_FOLDER=$APP_HOME/app/logs/ \ | |
| USAGE_LOGS_FOLDER=$APP_HOME/app/usage/ \ | |
| CONFIG_FOLDER=$APP_HOME/app/config/ \ | |
| XDG_CACHE_HOME=/tmp/xdg_cache/user_1000 \ | |
| TESSERACT_DATA_FOLDER=/usr/share/tessdata \ | |
| GRADIO_SERVER_NAME=0.0.0.0 \ | |
| GRADIO_SERVER_PORT=7860 \ | |
| PATH=$APP_HOME/.local/bin:$PATH \ | |
| PYTHONPATH=$APP_HOME/app \ | |
| PYTHONUNBUFFERED=1 \ | |
| PYTHONDONTWRITEBYTECODE=1 \ | |
| GRADIO_ALLOW_FLAGGING=never \ | |
| GRADIO_NUM_PORTS=1 \ | |
| GRADIO_ANALYTICS_ENABLED=False | |
| # Copy Python packages from the builder stage | |
| COPY --from=builder /install /usr/local/lib/python3.12/site-packages/ | |
| COPY --from=builder /install/bin /usr/local/bin/ | |
| # Reinstall protobuf into the final site-packages. Builder uses multiple `pip install --target=/install` | |
| # passes; that can break the `google` namespace so `google.protobuf` is missing and Paddle fails at import. | |
| RUN pip install --no-cache-dir "protobuf<=7.34.0" | |
| # Copy your application code and entrypoint | |
| COPY . ${APP_HOME}/app | |
| COPY entrypoint.sh ${APP_HOME}/app/entrypoint.sh | |
| # Fix line endings and set execute permissions | |
| RUN sed -i 's/\r$//' ${APP_HOME}/app/entrypoint.sh \ | |
| && chmod +x ${APP_HOME}/app/entrypoint.sh | |
| WORKDIR ${APP_HOME}/app | |
| # =================================================================== | |
| # FINAL Stage 3: The Lambda Image (runs as root for simplicity) | |
| # =================================================================== | |
| FROM base AS lambda | |
| # Set runtime ENV for Lambda mode | |
| ENV APP_MODE=lambda | |
| ENTRYPOINT ["/home/user/app/entrypoint.sh"] | |
| CMD ["lambda_entrypoint.lambda_handler"] | |
| # =================================================================== | |
| # FINAL Stage 4: The Gradio Image (runs as a secure, non-root user) | |
| # =================================================================== | |
| FROM base AS gradio | |
| # Set runtime ENV for Gradio mode | |
| ENV APP_MODE=gradio | |
| # Create non-root user | |
| RUN useradd -m -u 1000 user | |
| # Create the base application directory and set its ownership | |
| RUN mkdir -p ${APP_HOME}/app && chown user:user ${APP_HOME}/app | |
| # Create required sub-folders within the app directory and set their permissions | |
| # This ensures these specific directories are owned by 'user' | |
| RUN mkdir -p \ | |
| ${APP_HOME}/app/output \ | |
| ${APP_HOME}/app/input \ | |
| ${APP_HOME}/app/logs \ | |
| ${APP_HOME}/app/usage \ | |
| ${APP_HOME}/app/feedback \ | |
| ${APP_HOME}/app/config \ | |
| && chown user:user \ | |
| ${APP_HOME}/app/output \ | |
| ${APP_HOME}/app/input \ | |
| ${APP_HOME}/app/logs \ | |
| ${APP_HOME}/app/usage \ | |
| ${APP_HOME}/app/feedback \ | |
| ${APP_HOME}/app/config \ | |
| && chmod 755 \ | |
| ${APP_HOME}/app/output \ | |
| ${APP_HOME}/app/input \ | |
| ${APP_HOME}/app/logs \ | |
| ${APP_HOME}/app/usage \ | |
| ${APP_HOME}/app/feedback \ | |
| ${APP_HOME}/app/config | |
| # Now handle the /tmp and /var/tmp directories and their subdirectories, paddle, spacy, tessdata | |
| RUN mkdir -p /tmp/gradio_tmp /tmp/tld /tmp/matplotlib_cache /tmp /var/tmp ${XDG_CACHE_HOME} \ | |
| && chown user:user /tmp /var/tmp /tmp/gradio_tmp /tmp/tld /tmp/matplotlib_cache ${XDG_CACHE_HOME} \ | |
| && chmod 1777 /tmp /var/tmp /tmp/gradio_tmp /tmp/tld /tmp/matplotlib_cache \ | |
| && chmod 700 ${XDG_CACHE_HOME} \ | |
| && mkdir -p ${APP_HOME}/.paddlex \ | |
| && chown user:user ${APP_HOME}/.paddlex \ | |
| && chmod 755 ${APP_HOME}/.paddlex \ | |
| && mkdir -p ${APP_HOME}/.local/share/spacy/data \ | |
| && chown user:user ${APP_HOME}/.local/share/spacy/data \ | |
| && chmod 755 ${APP_HOME}/.local/share/spacy/data \ | |
| && mkdir -p /usr/share/tessdata \ | |
| && chown user:user /usr/share/tessdata \ | |
| && chmod 755 /usr/share/tessdata | |
| # Fix apply user ownership to all files in the home directory | |
| RUN chown -R user:user /home/user | |
| # Set permissions for Python executable | |
| RUN chmod 755 /usr/local/bin/python | |
| # Declare volumes (NOTE: runtime mounts will override permissions — handle with care) | |
| VOLUME ["/tmp/matplotlib_cache"] | |
| VOLUME ["/tmp/gradio_tmp"] | |
| VOLUME ["/tmp/tld"] | |
| VOLUME ["/home/user/app/output"] | |
| VOLUME ["/home/user/app/input"] | |
| VOLUME ["/home/user/app/logs"] | |
| VOLUME ["/home/user/app/usage"] | |
| VOLUME ["/home/user/app/feedback"] | |
| VOLUME ["/home/user/app/config"] | |
| VOLUME ["/home/user/.paddlex"] | |
| VOLUME ["/home/user/.local/share/spacy/data"] | |
| VOLUME ["/usr/share/tessdata"] | |
| VOLUME ["/tmp"] | |
| VOLUME ["/var/tmp"] | |
| USER user | |
| EXPOSE $GRADIO_SERVER_PORT | |
| ENTRYPOINT ["/home/user/app/entrypoint.sh"] | |
| CMD ["python", "app.py"] |