-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathDockerfile
More file actions
98 lines (84 loc) · 4.59 KB
/
Copy pathDockerfile
File metadata and controls
98 lines (84 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# Cortex MCP server — production image.
#
# Build: docker build -t cortex:latest .
# Run (DB-less, zero setup — the bare-container / registry-indexer
# contract, e.g. Glama's per-release microVM):
# docker run --rm -i cortex:latest
# tools/list answers with the full standalone tool set on the
# built-in SQLite backend, no external service, no env vars.
# Run (PostgreSQL, advanced):
# docker run --rm -i \
# -e DATABASE_URL=postgresql://user:pass@host:5432/cortex \
# -e CORTEX_MEMORY_POOL_INTERACTIVE_MAX=16 \
# cortex:latest
#
# Storage: SQLite by default (zero setup, matches CORTEX_RUNTIME=cowork
# below), or PostgreSQL 15+ with pgvector + pg_trgm when DATABASE_URL is
# set. The image does NOT bundle PostgreSQL; it connects to an external
# instance when one is configured — see mcp_server/infrastructure/
# memory_store.py for the auto/postgresql/sqlite backend-selection logic
# this image relies on (not duplicated here).
#
# Source: docs/program/phase-5-pool-admission-design.md §7.
FROM python:3.13-slim AS builder
WORKDIR /build
# Build deps only — stripped from the runtime image.
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY pyproject.toml README.md ./
COPY mcp_server ./mcp_server
COPY tests_py ./tests_py
# CPU-only torch wheel: sentence-transformers pulls torch transitively as
# a mandatory base dependency (pyproject.toml); pip's default index
# resolves the full CUDA build (~2GB across torch/cudnn/cusparselt/
# cublas/etc.) even though this image never uses a GPU. Pinning the CPU
# wheel index first, same as docker/Dockerfile:33-34, keeps this layer's
# download bounded — source: measured 2026-07-12, root Dockerfile build
# pulled 2GB+ of nvidia-cu13-* wheels before this pin was added (H2,
# fix/bare-container-contract root-cause report).
RUN pip install --no-cache-dir --upgrade pip build && \
pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cpu && \
pip install --no-cache-dir .[postgresql]
# ── Runtime stage ────────────────────────────────────────────────────────
FROM python:3.13-slim
LABEL org.opencontainers.image.source="https://github.com/cdeust/Cortex"
LABEL org.opencontainers.image.description="Cortex — neuroscience-backed memory system for Claude Code (MCP)"
LABEL org.opencontainers.image.licenses="MIT"
# libpq5 is the runtime side of libpq-dev — psycopg[binary] uses it.
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 \
&& rm -rf /var/lib/apt/lists/* \
&& useradd --create-home --uid 10001 cortex
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
USER cortex
WORKDIR /home/cortex
# CORTEX_RUNTIME=cowork opts into the store factory's existing permissive
# fallback path (mcp_server/infrastructure/memory_store.py::_construct_store):
# "auto" backend tries PostgreSQL when DATABASE_URL is set, and always
# falls back to the built-in SQLite store otherwise -- no external
# service required. Without this, the factory's default "cli" runtime
# treats an unreachable/default PostgreSQL URL as fatal (by design, for
# a developer laptop expecting Postgres) rather than falling back, which
# is wrong for a container with no external services attached. This does
# not affect `tools/list` (registration never touches the store), only
# the tool call paths (remember/recall/etc.) -- see bare-container-contract
# root-cause report, fact #11.
ENV CORTEX_RUNTIME=cowork
# Health check: the process is alive and the full tool-registration import
# chain (mcp_server.__main__, all 49 standalone tool handlers) succeeds --
# NOT a database reachability probe. Registration must succeed with zero
# external services (see CORTEX_RUNTIME above); a DB-touching healthcheck
# would fail this image's own DB-less contract. Exit 0 means ready; any
# non-zero from entrypoint propagates.
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD python -c "import mcp_server.__main__"
# MCP servers typically run stdio transport; no ports to expose.
# Prometheus metrics endpoint is served by the sidecar in Phase 7.1.
#
# Use `python -m mcp_server` — the invocation documented in the package's
# __main__.py — so the image never depends on a console-script name
# (`hypermnesia-mcp` / `cortex-doctor`) staying stable across renames.
ENTRYPOINT ["python", "-m", "mcp_server"]