| # Stage 1: Prepare Ollama with the model | |
| # Uses the official Ollama image as the base for this stage, which includes Ollama pre-installed. | |
| FROM ollama/ollama AS ollama-builder | |
| # Set OLLAMA_HOME for this stage to ensure consistent data location for Ollama. | |
| # Ollama in its default image often uses /root/.ollama. | |
| ENV OLLAMA_HOME="/root/.ollama" | |
| # Ensure the Ollama home directory exists within the builder stage. | |
| RUN mkdir -p ${OLLAMA_HOME} | |
| # Start Ollama server in the background and wait for it to be ready. | |
| # Then, pull the specified model from the Ollama library. | |
| # We explicitly use /usr/bin/ollama as confirmed by previous successful 'find' operations. | |
| # Using bash -c for robustness with backgrounding and multiple commands. | |
| # The sleep 15 is crucial to give Ollama enough time to start before attempting to pull. | |
| RUN bash -c "/usr/bin/ollama serve > \"${OLLAMA_HOME}/ollama_build.log\" 2>&1 & \ | |
| sleep 15 && \ | |
| /usr/bin/ollama pull krishna_choudhary/AI_Assistant_Chatbot || \ | |
| (cat \"${OLLAMA_HOME}/ollama_build.log\" && exit 1)" | |
| # Stage 2: Build the final application image with Streamlit and pre-configured Ollama | |
| # Using a lightweight Ubuntu base image for the final application. | |
| FROM ubuntu:22.04 | |
| # Create a non-root user and group for running the application. | |
| # This is crucial for security and to resolve permission issues at runtime on Hugging Face Spaces. | |
| ARG UID=1000 | |
| ARG GID=1000 | |
| RUN groupadd -r appgroup -g ${GID} && useradd -r -u ${UID} -g appgroup appuser | |
| # CRITICAL FIX: Explicitly create the home directory for appuser and set its ownership. | |
| # This resolves permission issues when Ollama (or any other application) | |
| # tries to access ~/.ollama or other files in the user's default home directory. | |
| RUN mkdir -p /home/appuser && chown appuser:appgroup /home/appuser | |
| # Set the working directory inside the container. | |
| WORKDIR /app | |
| # Install system dependencies for Streamlit (Python, pip) and general utilities (curl, git). | |
| # --no-install-recommends helps keep the image smaller. | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| python3.9 \ | |
| python3-pip \ | |
| build-essential \ | |
| curl \ | |
| software-properties-common \ | |
| git \ | |
| && rm -rf /var/lib/apt/lists/* \ | |
| && apt-get clean | |
| # Copy Python requirements file and install Python dependencies. | |
| COPY requirements.txt ./ | |
| RUN pip3 install --no-cache-dir -r /app/requirements.txt | |
| # Copy the Streamlit application source code into the container. | |
| COPY src/ ./src/ | |
| # --- Copy Ollama binaries and model data from the builder stage --- | |
| # Copy the Ollama executable from the first stage to the final image. | |
| # We know from previous logs that it's located at /usr/bin/ollama in the builder. | |
| COPY --from=ollama-builder /usr/bin/ollama /usr/local/bin/ollama | |
| # Set OLLAMA_HOME for the final image's runtime, pointing to a writable location within /app. | |
| ENV OLLAMA_HOME="/app/.ollama" | |
| # Copy the startup script into the container and make it executable. | |
| # This must happen *before* switching to the non-root user, as /usr/local/bin requires root permissions. | |
| COPY start.sh /usr/local/bin/start.sh | |
| RUN chmod +x /usr/local/bin/start.sh | |
| # Change ownership of the /app directory and its contents to the non-root user. | |
| # This is critical. It ensures the 'appuser' has full read/write/execute permissions within /app, | |
| # where Streamlit, Ollama's runtime data, and your application code reside. | |
| RUN chown -R appuser:appgroup /app | |
| # Switch to the non-root user. All subsequent commands in the Dockerfile (and the ENTRYPOINT) | |
| # will run as 'appuser', adhering to best security practices. | |
| USER appuser | |
| # --- Streamlit specific setup for Docker stability and configuration --- | |
| # Disable Streamlit usage statistics. | |
| ENV STREAMLIT_SERVER_BROWSER_GATHER_USAGE_STATS="false" | |
| # Set file watcher type to none for better stability in Docker environments, especially on Spaces. | |
| ENV STREAMLIT_SERVER_FILE_WATCHER_TYPE="none" | |
| # Set the port Streamlit will listen on. Hugging Face Spaces expose 8501 for Streamlit. | |
| ENV STREAMLIT_SERVER_PORT="8501" | |
| # Set the address Streamlit will bind to. | |
| ENV STREAMLIT_SERVER_ADDRESS="0.0.0.0" | |
| # Ensure Streamlit's cache directory is within the writable /app directory. | |
| ENV STREAMLIT_GLOBAL_DATA_PATH="/app/.streamlit" | |
| # No explicit mkdir -p needed here, as Streamlit will create it if needed, | |
| # and /app is now correctly owned by appuser. | |
| # Expose ports that the container will listen on. | |
| # 8501 for Streamlit, 11434 for Ollama API. | |
| EXPOSE 8501 | |
| EXPOSE 11434 | |
| # Define a healthcheck to ensure Streamlit is running and responsive. | |
| # This helps Hugging Face Spaces determine if your app is truly alive. | |
| HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health || exit 1 | |
| # Set the startup script as the main entrypoint for the container. | |
| ENTRYPOINT ["/usr/local/bin/start.sh"] |