Containerizing Your Graph Stack: Docker for RAG

Containerizing Your Graph Stack: Docker for RAG

Package your intelligence for the cloud. Learn how to build a production-grade Docker Compose setup that integrates Neo4j, your Python API, and vector stores into a single deployment unit.

Containerizing Your Graph Stack: Docker for RAG

In development, we ran Neo4j using a simple docker run command. In production, we need something more robust. A professional Graph RAG system has multiple moving parts: the Graph DB, the Vector Index, the FastAPI/Python Orchestrator, and a Message Queue (for asynchronous ingestion). To manage this "Orchestra," we use Docker Compose.

In this lesson, we will build a Production Dockerfile for our RAG agent and a docker-compose.yml file that links all our services together. We will learn how to handle Persistence (so your graph data doesn't disappear when the container restarts) and how to configure Health Checks to ensure the database is ready before the AI starts making queries.


1. The Multi-Service Architecture

For Graph RAG, we typically deploy:

  1. neo4j: The graph engine + GDS plugin.
  2. rag-api: Your Python code (LangChain/LangGraph).
  3. redis: For caching frequent graph results.
graph TD
    User((User)) -->|HTTP| API[Graph RAG API]
    API -->|Bolt| DB[(Neo4j DB)]
    API -->|TCP| Redis[(Redis Cache)]
    DB -->|Persistence| Vol[/Local Volume/]
    
    style DB fill:#4285F4,color:#fff
    style Redis fill:#f44336,color:#fff

2. The Python RAG Dockerfile

We need to package our Python code with all the dependencies from Module 10.

FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy source code
COPY . .

# Environment variables (Defaults)
ENV PORT=8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

3. The Orchestration (Docker Compose)

The "Master Blueprint" for your local or server environment.

version: '3.8'
services:
  neo4j:
    image: neo4j:enterprise # Or community
    ports:
      - "7474:7474"
      - "7687:7687"
    volumes:
      - ./data:/data
    environment:
      - NEO4J_PLUGINS=["graph-data-science", "apoc"]
      - NEO4J_AUTH=neo4j/password123
      
  rag-api:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      neo4j:
        condition: service_healthy
    env_file: .env

4. Why Persistence Matters (Volumes)

Container storage is Ephemeral. If the machine crashes, your 1-million node graph is gone.

  • The Solution: Always map the /data directory of your Neo4j container to a Local Volume on the host machine. This ensures that the graph "Memory" survives even if the "Body" (container) is replaced.

5. Summary and Exercises

Docker ensures that "It works on my machine" means "It works in the cloud."

  • Dockerfiles standardize the Python runtime.
  • Docker Compose manages the connectivity between the API and the Graph.
  • Volumes provide the long-term memory for your knowledge base.
  • Health Checks prevent the API from crashing while waiting for the DB to boot up.

Exercises

  1. Architecture Design: If you add a "Web Scraper" to your system, should it be inside the rag-api container or a separate service? Why?
  2. Environment Sync: Why is it dangerous to include your .env file inside the Docker image? What should you use instead? (Hint: env_file in Compose).
  3. Downtime Drill: Run docker-compose down. Now run docker-compose up. Did your data survive? If you used volumes, the answer is YES.

In the next lesson, we will move to the big clouds: Deploying to AWS, GCP, and Azure.

Subscribe to our newsletter

Get the latest posts delivered right to your inbox.

Subscribe on LinkedIn