| # 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! |
|
|
|
|