Docker Deployment
Memory Service is distributed as a Docker image, making it easy to deploy in any container environment. Before adapting these examples for a real environment, review the Security Hardening guide for image pinning, secret handling, TLS, management endpoints, and attachment-download safety.
Quick Start
Use a pinned release image and pass generated local credentials through environment variables:
export DB_PASSWORD="$(openssl rand -base64 32)"
docker run -d \
--name memory-service \
-p 8080:8080 \
-p 127.0.0.1:8085:8085 \
--read-only \
--user 10001:10001 \
--cap-drop ALL \
--security-opt no-new-privileges:true \
--tmpfs /var/lib/memory-service/tmp:uid=10001,gid=10001,mode=0700 \
-e MEMORY_SERVICE_DB_URL="postgres://postgres:${DB_PASSWORD}@host.docker.internal:5432/memoryservice?sslmode=disable" \
-e MEMORY_SERVICE_HOST=0.0.0.0 \
-e MEMORY_SERVICE_TLS=false \
-e MEMORY_SERVICE_MANAGEMENT_PORT=8085 \
-e MEMORY_SERVICE_MANAGEMENT_HOST=0.0.0.0 \
-e MEMORY_SERVICE_MANAGEMENT_TLS=false \
-e MEMORY_SERVICE_MANAGEMENT_ALLOW_NON_LOOPBACK=true \
-e MEMORY_SERVICE_TEMP_DIR=/var/lib/memory-service/tmp \
ghcr.io/chirino/memory-service:${PROJECT_VERSION}
Docker Compose
For a complete local setup with all dependencies, use the repository compose file:
docker compose up -d
A minimal production-style compose file should keep secrets outside the file and pin the service image. Keep browser-facing deployments behind TLS and keep management endpoints on an internal path; see Security Hardening for the full production checklist.
services:
memory-service:
image: ghcr.io/chirino/memory-service:${PROJECT_VERSION}
read_only: true
user: "10001:10001"
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
ports:
- "127.0.0.1:8080:8080"
environment:
- MEMORY_SERVICE_DB_URL=postgres://postgres:${DB_PASSWORD}@postgres:5432/memoryservice?sslmode=disable
- MEMORY_SERVICE_DB_MIGRATE_AT_START=true
- MEMORY_SERVICE_HOST=0.0.0.0
- MEMORY_SERVICE_TLS=false
- MEMORY_SERVICE_MANAGEMENT_PORT=8085
- MEMORY_SERVICE_MANAGEMENT_HOST=0.0.0.0
- MEMORY_SERVICE_MANAGEMENT_TLS=false
- MEMORY_SERVICE_MANAGEMENT_ALLOW_NON_LOOPBACK=true
- MEMORY_SERVICE_TEMP_DIR=/var/lib/memory-service/tmp
volumes:
- memory_service_tmp:/var/lib/memory-service/tmp
depends_on:
postgres:
condition: service_healthy
postgres:
image: pgvector/pgvector:pg18
environment:
- POSTGRES_DB=memoryservice
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
volumes:
postgres_data:
memory_service_tmp:
Environment Variables
Database Configuration
| Variable | Description | Default |
|---|---|---|
MEMORY_SERVICE_DB_KIND | Database type (postgres, sqlite, or mongo) | postgres |
MEMORY_SERVICE_DB_URL | Database connection URL | - |
MEMORY_SERVICE_DB_MIGRATE_AT_START | Run schema migrations on startup | true |
MEMORY_SERVICE_DB_MAX_OPEN_CONNS | Maximum open database connections | 25 |
MEMORY_SERVICE_DB_MAX_IDLE_CONNS | Idle/minimum connections in pool | 5 |
Vector Store Configuration
| Variable | Description | Default |
|---|---|---|
MEMORY_SERVICE_VECTOR_KIND | Vector store type (none, pgvector, qdrant, sqlite) | none |
MEMORY_SERVICE_EMBEDDING_KIND | Embedding provider (none, local, openai) | local |
MEMORY_SERVICE_EMBEDDING_OPENAI_API_KEY | OpenAI API key for embeddings | - |
SQLite Example
services:
memory-service:
image: ghcr.io/chirino/memory-service:${PROJECT_VERSION}
environment:
MEMORY_SERVICE_DB_KIND: sqlite
MEMORY_SERVICE_DB_URL: /data/memory-service.sqlite
MEMORY_SERVICE_ATTACHMENTS_KIND: fs
MEMORY_SERVICE_VECTOR_KIND: sqlite
MEMORY_SERVICE_EMBEDDING_KIND: local
volumes:
- ./data:/data
With this configuration, attachment bytes are stored under /data/memory-service.sqlite.attachments unless MEMORY_SERVICE_ATTACHMENTS_FS_DIR is set explicitly.
Authentication
| Variable | Description | Default |
|---|---|---|
MEMORY_SERVICE_OIDC_ISSUER | OIDC issuer URL | - |
MEMORY_SERVICE_OIDC_ALLOWED_CLIENTS | Optional comma-separated OIDC client IDs allowed to call Memory Service; empty allows any client from the configured issuer | - |
MEMORY_SERVICE_OIDC_ALLOWED_AUDIENCES | Required comma-separated OIDC audiences accepted by Memory Service when OIDC is enabled | - |
MEMORY_SERVICE_OIDC_ROLE_CLAIMS | JSON array of RFC 6901 claim paths used for claim-derived roles | ["/realm_access/roles"] |
MEMORY_SERVICE_OIDC_TLS_INSECURE_SKIP_VERIFY | Skip TLS certificate verification for OIDC discovery/JWKS requests; rejected outside testing mode | false |
MEMORY_SERVICE_API_KEYS_<CLIENT> | API key(s) for a client ID | - |
Health Checks
The container exposes health endpoints:
# Liveness
curl http://localhost:8080/health
# Readiness
curl http://localhost:8080/ready
Configure in Docker Compose:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/ready"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
Resource Limits
Set appropriate resource limits:
services:
memory-service:
deploy:
resources:
limits:
cpus: "2"
memory: 1G
reservations:
cpus: "0.5"
memory: 512M
Production Configuration
For production deployments:
services:
memory-service:
image: ghcr.io/chirino/memory-service:999-SNAPSHOT
restart: unless-stopped
read_only: true
user: "10001:10001"
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
environment:
- MEMORY_SERVICE_DB_URL=postgres://postgres:${DB_PASSWORD}@postgres:5432/memoryservice?sslmode=disable
- MEMORY_SERVICE_HOST=0.0.0.0
- MEMORY_SERVICE_PLAIN_TEXT=false
- MEMORY_SERVICE_MANAGEMENT_PORT=8085
- MEMORY_SERVICE_MANAGEMENT_HOST=0.0.0.0
- MEMORY_SERVICE_MANAGEMENT_PLAIN_TEXT=false
- MEMORY_SERVICE_MANAGEMENT_ALLOW_NON_LOOPBACK=true
- MEMORY_SERVICE_TEMP_DIR=/var/lib/memory-service/tmp
- MEMORY_SERVICE_TLS_CERT_FILE=/certs/server.crt
- MEMORY_SERVICE_TLS_KEY_FILE=/certs/server.key
volumes:
- ./certs:/certs:ro
- memory_service_tmp:/var/lib/memory-service/tmp
volumes:
memory_service_tmp:
This example is a starting point, not a complete security boundary. Add a real database, OIDC audience configuration, non-plain encryption, trusted TLS material, exact CORS origins when browser clients are used, and deployment-specific network controls as described in Security Hardening.
Multi-Container Setup
With separate embedding service:
services:
memory-service:
image: ghcr.io/chirino/memory-service:${PROJECT_VERSION}
environment:
- MEMORY_SERVICE_EMBEDDING_URL=http://embedding-service:8000
depends_on:
- embedding-service
- postgres
embedding-service:
image: your-embedding-service:latest
environment:
- MODEL=text-embedding-ada-002
- OPENAI_API_KEY=${OPENAI_API_KEY}
postgres:
image: pgvector/pgvector:pg18
# ... configuration
Logging
View container logs:
docker logs -f memory-service
The service writes structured log output to stdout. Use your container runtime’s log driver or a sidecar to ship logs to your preferred backend.
Networking
For inter-container communication:
networks:
memory-network:
driver: bridge
services:
memory-service:
networks:
- memory-network
postgres:
networks:
- memory-network
my-agent:
networks:
- memory-network
environment:
- MEMORY_SERVICE_URL=http://memory-service:8080
Next Steps
- Learn about Service Configuration
- Review the Security Hardening checklist