# Dockerfile Explanation This Dockerfile is specifically designed for **LangGraph Cloud/LangServe deployment**. It uses the official LangGraph API base image and configures your agent graphs to be served as REST APIs. ## Line-by-Line Breakdown ### 1. Base Image (Line 1) ```dockerfile FROM langchain/langgraph-api:3.12 ``` - **Purpose**: Uses the official LangGraph API base image with Python 3.12 - **What it includes**: Pre-configured LangGraph runtime, LangServe server, and all LangGraph dependencies - **Why**: This image already has everything needed to serve LangGraph workflows as REST APIs --- ### 2. Install Node Dependencies (Line 9) ```dockerfile RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt nodes ``` - **Purpose**: Installs the `nodes` package (likely a dependency from your `langgraph.json`) - **`PYTHONDONTWRITEBYTECODE=1`**: Prevents creating `.pyc` files (smaller image) - **`uv pip`**: Uses `uv` (fast Python package installer) instead of regular `pip` - **`--system`**: Installs to system Python (not virtual env) - **`--no-cache-dir`**: Doesn't cache pip downloads (smaller image) - **`-c /api/constraints.txt`**: Uses constraint file from base image (ensures compatible versions) --- ### 3. Copy Your Code (Line 14) ```dockerfile ADD . /deps/job_writer ``` - **Purpose**: Copies your entire project into `/deps/job_writer` in the container - **Why `/deps/`**: LangGraph API expects dependencies in this directory - **What gets copied**: All your source code, `pyproject.toml`, `requirements.txt`, etc. --- ### 4. Install Your Package (Lines 19-21) ```dockerfile RUN for dep in /deps/*; do echo "Installing $dep"; if [ -d "$dep" ]; then echo "Installing $dep"; (cd "$dep" && PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir -c /api/constraints.txt -e .); fi; done ``` - **Purpose**: Installs your `job_writer` package in editable mode (`-e`) - **How it works**: - Loops through all directories in `/deps/` - For each directory, changes into it and runs `pip install -e .` - The `-e` flag installs in "editable" mode (changes to code are reflected) - **Why**: Makes your package importable as `job_writing_agent` inside the container --- ### 5. Register Your Graphs (Line 25) ```dockerfile ENV LANGSERVE_GRAPHS='{"job_app_graph": "/deps/job_writer/src/job_writing_agent/workflow.py:job_app_graph", ...}' ``` - **Purpose**: Tells LangServe which graphs to expose as REST APIs - **Format**: JSON mapping of `graph_name` → `module_path:attribute_name` - **What it does**: - `job_app_graph` → Exposes `JobWorkflow.job_app_graph` property as an API endpoint - `research_workflow` → Exposes the research subgraph - `data_loading_workflow` → Exposes the data loading subgraph - **Result**: Each graph becomes a REST API endpoint like `/invoke/job_app_graph` --- ### 6. Protect LangGraph API (Lines 33-35) ```dockerfile RUN mkdir -p /api/langgraph_api /api/langgraph_runtime /api/langgraph_license && \ touch /api/langgraph_api/__init__.py /api/langgraph_runtime/__init__.py /api/langgraph_license/__init__.py RUN PYTHONDONTWRITEBYTECODE=1 uv pip install --system --no-cache-dir --no-deps -e /api ``` - **Purpose**: Prevents your dependencies from accidentally overwriting LangGraph API packages - **How**: 1. Creates placeholder `__init__.py` files for LangGraph packages 2. Reinstalls LangGraph API (without dependencies) to ensure it's not overwritten - **Why**: If your `requirements.txt` has conflicting versions, this ensures LangGraph API stays intact --- ### 7. Cleanup Build Tools (Lines 37-41) ```dockerfile RUN pip uninstall -y pip setuptools wheel RUN rm -rf /usr/local/lib/python*/site-packages/pip* ... RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx ``` - **Purpose**: Removes all build tools to make the image smaller and more secure - **What gets removed**: - `pip`, `setuptools`, `wheel` (Python build tools) - `uv` and `uvx` (package installers) - **Why**: These tools aren't needed at runtime, only during build - **Security**: Smaller attack surface (can't install malicious packages at runtime) --- ### 8. Set Working Directory (Line 45) ```dockerfile WORKDIR /deps/job_writer ``` - **Purpose**: Sets the default directory when the container starts - **Why**: Makes it easier to reference files relative to your project root --- ## How It Works at Runtime When this container runs: 1. **LangServe starts automatically** (from base image) 2. **Reads `LANGSERVE_GRAPHS`** environment variable 3. **Imports your graphs** from the specified paths 4. **Exposes REST API endpoints**: - `POST /invoke/job_app_graph` - Main workflow - `POST /invoke/research_workflow` - Research subgraph - `POST /invoke/data_loading_workflow` - Data loading subgraph 5. **Handles state management** automatically (checkpointing, persistence) ## Example API Usage Once deployed, you can call your agent like this: ```bash curl -X POST http://your-deployment/invoke/job_app_graph \ -H "Content-Type: application/json" \ -d '{ "resume_path": "...", "job_description_source": "...", "content": "cover_letter" }' ``` ## Key Points ✅ **Optimized for LangGraph Cloud** - Uses official base image ✅ **Automatic API generation** - No need to write FastAPI code ✅ **State management** - Built-in checkpointing and persistence ✅ **Security** - Removes build tools from final image ✅ **Small image** - No-cache installs, no bytecode files This is the **easiest deployment option** for LangGraph apps - just build and push this Docker image!