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.
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