Back to Theory
Tutorial7 min read · June 16, 2026

Deploying Feather DB with Docker: Self-Hosted Context Infrastructure in 10 Minutes

feather-serve ships with a Docker Compose setup, REST API, Atlas admin SPA, and MCP server. Here's the complete production-ready deployment — persistent volume, embedding provider, health checks, and Python client wiring.

F
Feather DB
Engineering

What you're deploying

feather-serve is the production interface for Feather DB. It wraps the embedded C++ engine in a FastAPI server that exposes:

  • A REST API at /api/v1/ — for Python clients and curl
  • An MCP server at /mcp — for Claude Desktop and MCP-compatible agents
  • The Atlas admin SPA at /admin/ — a web UI for browsing memories and running searches

The Docker deployment adds persistence (named volume), automatic restart, and environment-based configuration for the embedding provider.

Step 1: Clone and build

# Clone the feather repository
git clone https://github.com/feather-store/feather.git
cd feather

# Build the Docker image
docker compose -f feather-api/docker-compose.yml build

# Confirm the image built successfully
docker images | grep feather
# feather-api   latest   a1b2c3d4e5f6   2 minutes ago   412MB

Step 2: Create the .env file

Create feather-api/.env with your configuration:

# feather-api/.env

# API authentication key — set this to a random secret
FEATHER_API_KEY=your-secret-api-key-here

# Embedding provider — pick one:
# Options: gemini | openai | voyage | cohere | ollama
FEATHER_EMBED_PROVIDER=gemini

# API key for your chosen provider
GOOGLE_API_KEY=your-google-api-key
# OPENAI_API_KEY=your-openai-api-key
# VOYAGE_API_KEY=your-voyage-api-key
# COHERE_API_KEY=your-cohere-api-key

# Performance tuning
FEATHER_LOAD_THREADS=8
# FEATHER_QUANTIZE_RAM=1  # uncomment to enable int8 RAM quantization

# Server config
FEATHER_PORT=7700
FEATHER_DIM=768

Step 3: Review the docker-compose.yml

The default compose file in feather-api/docker-compose.yml:

version: '3.9'

services:
  feather-api:
    image: feather-api:latest
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "${FEATHER_PORT:-7700}:7700"
    volumes:
      # Named volume for persistence across container restarts
      - feather-data:/data
    environment:
      - FEATHER_API_KEY=${FEATHER_API_KEY}
      - FEATHER_EMBED_PROVIDER=${FEATHER_EMBED_PROVIDER:-gemini}
      - GOOGLE_API_KEY=${GOOGLE_API_KEY:-}
      - OPENAI_API_KEY=${OPENAI_API_KEY:-}
      - VOYAGE_API_KEY=${VOYAGE_API_KEY:-}
      - COHERE_API_KEY=${COHERE_API_KEY:-}
      - FEATHER_LOAD_THREADS=${FEATHER_LOAD_THREADS:-4}
      - FEATHER_DIM=${FEATHER_DIM:-768}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7700/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 15s
    restart: unless-stopped

volumes:
  feather-data:
    driver: local

Step 4: Start the service

# Start in detached mode
docker compose -f feather-api/docker-compose.yml up -d

# Watch the logs until the server is ready
docker compose -f feather-api/docker-compose.yml logs -f
# feather-api  | INFO: Feather DB v0.15.1
# feather-api  | INFO: Embedding provider: gemini (text-embedding-004)
# feather-api  | INFO: Index loaded in 0.02s (0 vectors)
# feather-api  | INFO: Serving at http://0.0.0.0:7700
# feather-api  | INFO: Atlas admin at http://0.0.0.0:7700/admin/
# feather-api  | INFO: MCP endpoint at http://0.0.0.0:7700/mcp

Step 5: Verify the health check

# Health check endpoint
curl http://localhost:7700/health
# {"status": "ok", "version": "0.15.1", "vectors": 0, "dim": 768}

# Test with the API key
curl -H "Authorization: Bearer your-secret-api-key-here" \
     http://localhost:7700/api/v1/stats
# {"total_vectors": 0, "namespaces": 0, "file_size_mb": 0.002}

Step 6: Browse the admin SPA

Open http://localhost:7700/admin/ in your browser. The Atlas admin SPA allows you to:

  • Browse all stored memories by namespace and entity
  • Run manual semantic searches and see scores
  • Inspect memory metadata and recall counts
  • Add and delete individual memories
  • View the context graph for any memory

The admin SPA is read-write but requires the same API key for any mutations. It's useful for debugging what your agent is remembering and why certain memories surface.

Step 7: Connect from a Python client

import requests

FEATHER_URL = "http://localhost:7700"
FEATHER_API_KEY = "your-secret-api-key-here"

headers = {"Authorization": f"Bearer {FEATHER_API_KEY}"}

def add_memory(text: str, namespace: str = "default",
               entity: str = "general", importance: float = 1.0):
    """Add a memory via the REST API (text is embedded server-side)."""
    response = requests.post(
        f"{FEATHER_URL}/api/v1/add",
        headers=headers,
        json={
            "text": text,
            "namespace": namespace,
            "entity": entity,
            "importance": importance
        }
    )
    response.raise_for_status()
    return response.json()

def search_memory(query: str, namespace: str = "default",
                   k: int = 5, half_life: int = 30):
    """Search memories via the REST API."""
    response = requests.post(
        f"{FEATHER_URL}/api/v1/search",
        headers=headers,
        json={
            "query": query,
            "namespace": namespace,
            "k": k,
            "half_life": half_life
        }
    )
    response.raise_for_status()
    return response.json()["results"]

# Usage
mem = add_memory(
    text="The feather-serve Docker deployment uses a named volume for persistence.",
    namespace="project-docs",
    entity="deployment",
    importance=1.5
)
print(f"Saved memory id={mem['id']}")

results = search_memory(
    query="How does Docker persistence work for feather-serve?",
    namespace="project-docs"
)
for r in results:
    print(f"score={r['score']:.3f}: {r['text'][:80]}")

Production configuration notes

Named volume: The feather-data named volume persists the .feather file across container restarts and image updates. Never use a bind mount to a temporary directory in production — you'll lose all memories on container restart.

Restart policy: restart: unless-stopped ensures the service recovers from crashes and starts on host reboot. Change to always if you want it to start even when you manually stopped it.

Embedding provider in Docker: The embedding provider is set via environment variable. To switch from Gemini to OpenAI, update FEATHER_EMBED_PROVIDER=openai and add OPENAI_API_KEY in your .env file, then restart the container. All existing memories remain valid as long as you use the same embedding dimension.

Reverse proxy: For production HTTPS, put Nginx or Caddy in front of feather-serve. Add a proxy_pass http://feather-api:7700 directive and a Let's Encrypt certificate. The MCP endpoint and admin SPA both work behind a reverse proxy with no additional configuration.

Install: pip install feather-db · GitHub: github.com/feather-store/feather