mem0 / Dockerfile
keithproject's picture
fix: bake LLM/embedder config into Dockerfile ENV — no DB needed
0b25cc0
Raw
History Blame Contribute Delete
7.49 kB
# mem0 Self-Hosted - Dockerfile
# Multi-stage build for mem0 self-hosted on HF Spaces
# Stage 1: Build mem0 API and Dashboard
# Stage 2: Runtime with PostgreSQL, supervisord, nginx
# =============================================================================
# Stage 1: Build mem0 API (Python)
# =============================================================================
FROM python:3.12-slim-bookworm AS api-builder
WORKDIR /build/api
# Install system dependencies for building
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
git \
curl \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Copy mem0 server source and root requirements
COPY server/ /build/api/
COPY requirements.txt /build/api/requirements.txt
# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# =============================================================================
# Stage 2: Build Dashboard (Next.js)
# =============================================================================
FROM node:20-alpine AS dashboard-builder
WORKDIR /build/dashboard
# Copy dashboard config files (package.json, next.config, tailwind, etc.)
COPY server/dashboard/ /build/dashboard/
# Fetch dashboard source from upstream mem0 repo (sparse clone of src/ and public/)
RUN apk add --no-cache git \
&& git clone --depth 1 --filter=blob:none --sparse \
https://github.com/mem0ai/mem0.git /tmp/mem0src \
&& cd /tmp/mem0src && git sparse-checkout set server/dashboard/src server/dashboard/public \
&& rm -rf /build/dashboard/src && cp -r /tmp/mem0src/server/dashboard/src /build/dashboard/src \
&& (cp -r /tmp/mem0src/server/dashboard/public /build/dashboard/public 2>/dev/null || mkdir -p /build/dashboard/public) \
&& rm -rf /tmp/mem0src
# Install dependencies
RUN npm install --no-audit --legacy-peer-deps
# Build Next.js standalone output - NEXT_PUBLIC_API_URL must be set at build time
ENV NEXT_TELEMETRY_DISABLED=1
ENV NEXT_PUBLIC_API_URL=/api
RUN npm run build
# NOTE: MEM0_LLM_* and MEM0_EMBEDDER_* are set in the runtime stage below
# Fix upstream bug: .env.http://localhost:7860/api is not a valid JS identifier
# Affects both server chunks (process.env.) and minified client bundles (s.env.)
# Server-side: replace with literal internal API URL
# Client-side: restore to NEXT_PUBLIC_API_URL with hardcoded fallback
RUN find /build/dashboard/.next -name '*.js' -exec \
sed -i 's|process\.env\.http://localhost:7860/api|"http://localhost:8000"|g' {} + 2>/dev/null || true && \
find /build/dashboard/.next -name '*.js' -exec \
sed -i 's|\.env\.http://localhost:7860/api|.env.NEXT_PUBLIC_API_URL||\"http://localhost:7860/api\"|g' {} + 2>/dev/null || true
# NOTE: Do NOT rewrite client PUT/DELETE on /api/auth/refresh to POST.
# Upstream contract (correct): PUT stores refresh_token cookie, POST rotates it,
# DELETE clears it. nginx routes /api/auth/refresh to the Next.js dashboard
# (see nginx.conf), which owns the httpOnly cookie — not to FastAPI.'
# =============================================================================
# Stage 3: Runtime - python:3.12-slim-bookworm with PostgreSQL, supervisord, nginx
# Pinned to bookworm so glibc matches api-builder exactly
# =============================================================================
FROM python:3.12-slim-bookworm
SHELL ["/bin/bash", "-c"]
# Environment variables
ENV PYTHONUNBUFFERED=1
ENV DEBIAN_FRONTEND=noninteractive
ENV PGDATA=/data/pgdata
ENV PGPORT=5432
# Default LLM/Embedder config — baked in so Space works without manual /api/configure
# Override via HF Space Secrets if needed
ENV MEM0_LLM_PROVIDER=openai
ENV MEM0_LLM_MODEL=memory-hub
ENV MEM0_LLM_API_KEY=sk-fc73b173f8a45ee0-e5chee-3b30445a
ENV MEM0_LLM_BASE_URL=https://deironk-9router.hf.space/v1
ENV MEM0_LLM_MAX_TOKENS=4000
ENV MEM0_LLM_TEMPERATURE=0.2
ENV MEM0_EMBEDDER_PROVIDER=openai
ENV MEM0_EMBEDDER_MODEL=gemini/gemini-embedding-001
ENV MEM0_EMBEDDER_API_KEY=sk-fc73b173f8a45ee0-e5chee-3b30445a
ENV MEM0_EMBEDDER_BASE_URL=https://deironk-9router.hf.space/v1
ENV MEM0_EMBEDDER_DIMS=1536
# Add PGDG apt repository for PostgreSQL 15 + pgvector
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates gnupg \
&& curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /usr/share/keyrings/postgresql.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list \
&& rm -rf /var/lib/apt/lists/*
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
# PostgreSQL 15 + pgvector (from PGDG)
postgresql-15 \
postgresql-15-pgvector \
postgresql-client-15 \
# Node.js for dashboard runtime
nodejs \
npm \
# Process management
supervisor \
# Web server
nginx \
# Utilities
curl \
ca-certificates \
gosu \
procps \
vim \
nano \
htop \
bash \
git \
git-lfs \
gettext-base \
openssh-client \
tar \
gzip \
xz-utils \
bzip2 \
rsync \
&& rm -rf /var/lib/apt/lists/*
# Create UID 1000 user for HF Spaces FUSE compatibility
RUN useradd -u 1000 -m -d /opt/data mem0 && \
mkdir -p /opt/data/{pgdata,sessions,logs,history} && \
chown -R 1000:1000 /opt/data
# Copy built API from builder stage (python:3.12-slim base means Python runtime is already present)
COPY --from=api-builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=api-builder /usr/local/bin/uvicorn /usr/local/bin/uvicorn
COPY --from=api-builder /build/api /opt/mem0/api
# Copy built Dashboard from builder stage
# dashboard/entrypoint.sh does `cd /app`, so deploy there
COPY --from=dashboard-builder /build/dashboard/.next/standalone /app
COPY --from=dashboard-builder /build/dashboard/.next/static /app/.next/static
COPY --from=dashboard-builder /build/dashboard/public /app/public
COPY --from=dashboard-builder /build/dashboard/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh && \
chown -R 1000:1000 /app
# Keep /opt/mem0/dashboard as a symlink for compatibility
RUN ln -s /app /opt/mem0/dashboard
# Copy configuration files
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY nginx.conf /etc/nginx/nginx.conf
COPY nginx-proxy.conf /etc/nginx/proxy.conf
COPY entrypoint.sh /entrypoint.sh
COPY init-db.sh /init-db.sh
COPY postgres-fuse-wrap /usr/local/bin/postgres-fuse-wrap
RUN chmod +x /entrypoint.sh /init-db.sh /usr/local/bin/postgres-fuse-wrap
# Create runtime directories writable by mem0 (UID 1000)
RUN mkdir -p /var/log/nginx /var/cache/nginx /run/nginx \
/var/log/supervisor /run/supervisor /var/run/postgresql \
/var/lib/nginx/body /var/lib/nginx/fastcgi \
/var/lib/nginx/proxy /var/lib/nginx/scgi /var/lib/nginx/uwsgi \
/app && \
chown -R 1000:1000 /var/log/nginx /var/cache/nginx /run/nginx \
/var/log/supervisor /run/supervisor /var/run/postgresql \
/var/lib/nginx
# Expose HF Spaces port
EXPOSE 7860
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost:7860/health || exit 1
# Run as root for initialization, then drop to UID 1000
ENTRYPOINT ["/entrypoint.sh"]