Docker Compose Integration
Spring Boot 3.1+ includes built-in Docker Compose support that can automatically start and configure services defined in a compose.yaml file. This makes it easy to run Memory Service and its dependencies during development.
Overview
Spring Boot’s Docker Compose integration provides:
- Automatic service discovery - Spring Boot detects running containers
- Service connection - Automatic configuration via
ConnectionDetails - Health checks - Waits for services to be ready before starting the app
- Clean shutdown - Stops containers when the app shuts down (optional)
Setup
Add the Docker Compose dependency to your pom.xml:
<dependency>
<groupId>io.github.chirino.memory-service</groupId>
<artifactId>memory-service-spring-boot-docker-compose-starter</artifactId>
<version>999-SNAPSHOT</version>
</dependency>
Place a compose.yaml file in your project root (Spring Boot auto-detects it):
services:
postgres:
image: pgvector/pgvector:pg18
environment:
POSTGRES_DB: memory_service
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "55432:5432"
volumes:
- ../../../../deploy/keycloak/postgres-init-keycloak.sql:/docker-entrypoint-initdb.d/postgres-init-keycloak.sql:ro
tmpfs:
- /var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 10
keycloak:
image: quay.io/keycloak/keycloak:26.6.3
command: ["start-dev", "--import-realm"]
environment:
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
KC_DB: postgres
KC_DB_URL_HOST: postgres
KC_DB_URL_DATABASE: keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: keycloak
KC_HTTP_RELATIVE_PATH: /
KC_HEALTH_ENABLED: "true"
KC_HOSTNAME: http://${KEYCLOAK_HOSTNAME:-localhost}:${KEYCLOAK_HOSTNAME_PORT:-8081}
KC_HOSTNAME_BACKCHANNEL_DYNAMIC: "true"
volumes:
- ../../../../deploy/keycloak/memory-service-realm.json:/opt/keycloak/data/import/memory-service-realm.json:ro
depends_on:
postgres:
condition: service_healthy
ports:
- "8081:8080"
healthcheck:
test:
[
"CMD-SHELL",
"exec 3<>/dev/tcp/localhost/9000 && printf 'GET /health/ready HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n' >&3 && cat <&3 | grep -q 'UP'",
]
interval: 10s
timeout: 5s
retries: 15
start_period: 30s
memory-service:
image: ghcr.io/chirino/memory-service:latest
environment:
MEMORY_SERVICE_API_KEYS_AGENT: agent-api-key-1,agent-api-key-2
# Browser-visible local developer-console credential. Never use in production.
MEMORY_SERVICE_API_KEYS_DEVELOPER_FRONTEND: developer-frontend-api-key
MEMORY_SERVICE_HOST: 0.0.0.0
MEMORY_SERVICE_PLAIN_TEXT: "true"
MEMORY_SERVICE_TLS: "false"
MEMORY_SERVICE_ALLOW_NON_LOOPBACK_PLAINTEXT: "true"
# ── Self-contained storage ─────
MEMORY_SERVICE_DB_KIND: sqlite
MEMORY_SERVICE_DB_URL: file:/tmp/memory-service-dev/memory-service.db
MEMORY_SERVICE_DB_MIGRATE_AT_START: "true"
MEMORY_SERVICE_CACHE_KIND: local
MEMORY_SERVICE_MANAGEMENT_ON_MAIN_LISTENER: "true"
MEMORY_SERVICE_VECTOR_KIND: sqlite
MEMORY_SERVICE_EMBEDDING_KIND: local
MEMORY_SERVICE_ATTACHMENTS_KIND: fs
MEMORY_SERVICE_ATTACHMENTS_FS_DIR: /tmp/memory-service-dev/attachments
MEMORY_SERVICE_TEMP_DIR: /tmp/memory-service-dev/tmp
# ── Authentication & authorization ─────────────────────────
MEMORY_SERVICE_OIDC_ISSUER: http://${KEYCLOAK_HOSTNAME:-localhost}:${KEYCLOAK_HOSTNAME_PORT:-8081}/realms/memory-service
MEMORY_SERVICE_OIDC_DISCOVERY_URL: http://keycloak:8080/realms/memory-service
MEMORY_SERVICE_OIDC_ALLOWED_CLIENTS: memory-service-client,frontend,developer-frontend
MEMORY_SERVICE_OIDC_ALLOWED_AUDIENCES: memory-service
MEMORY_SERVICE_ROLES_ADMIN_OIDC_ROLE: admin
MEMORY_SERVICE_ROLES_AUDITOR_OIDC_ROLE: auditor
MEMORY_SERVICE_ROLES_ADMIN_CLIENTS: developer_frontend
MEMORY_SERVICE_ROLES_INDEXER_CLIENTS: agent
# ── Developer Frontend ─────────────────────────────────────
MEMORY_SERVICE_DEVELOPER_FRONTEND_ENABLED: "true"
MEMORY_SERVICE_DEVELOPER_FRONTEND_CLIENT_ID: developer_frontend
MEMORY_SERVICE_DEVELOPER_FRONTEND_AUTH_MODE: api-key
MEMORY_SERVICE_DEVELOPER_FRONTEND_API_KEY: developer-frontend-api-key
MEMORY_SERVICE_BASE_URL: "http://localhost:8082"
MEMORY_SERVICE_CORS_ENABLED: "true"
MEMORY_SERVICE_CORS_ORIGINS: "http://localhost:3000"
# ── Encryption ─────────────────────────────────────────────
# Well-known development key; replace with a secure key in production.
MEMORY_SERVICE_ENCRYPTION_KIND: dek
MEMORY_SERVICE_ENCRYPTION_DEK_KEY: ${MEMORY_SERVICE_ENCRYPTION_DEK_KEY:-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef}
depends_on:
keycloak:
condition: service_healthy
ports:
- "8082:8080"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/ready || exit 1"]
interval: 10s
timeout: 5s
retries: 12
This configuration uses self-contained storage for the memory service (SQLite, local cache, filesystem attachments). The integrated developer console at http://localhost:8082/developer skips OAuth and uses its dedicated API-key admin client. Keycloak remains available for the Spring chat application’s end-user login flow.
The developer console key is deliberately exposed through /developer/config.json, so anyone who can reach port 8082 receives local admin access. This is appropriate only for isolated local development and must never be enabled in production. The console does not send X-User-ID; that header selects user context for normal user APIs and is not a credential for Admin APIs.
Key features:
- SQLite for memory service database storage (ephemeral)
- Local cache for in-memory caching
- Filesystem for attachment storage
- Local embeddings for vector operations
- Keycloak for the chat application’s OIDC authentication (uses Postgres)
- Integrated developer frontend at
http://localhost:8082/developer
Access points:
- Memory service API:
http://localhost:8082 - Developer frontend:
http://localhost:8082/developer - Keycloak admin console:
http://localhost:8081(admin/admin) - API key:
agent-api-key-1
Service Connection
Spring Boot automatically detects the memory-service container and provides connection details via MemoryServiceConnectionDetails. The starter uses these connection
details to configure the REST and gRPC clients.
Make sure you comment out the memory-service.client properties in your application.properties file to pickup the connection details from the Docker Compose file.
# These will override Docker Compose connection details if set
#memory-service.client.url=http://localhost:8082
#memory-service.client.api-key=agent-api-key-1
Running the Application
When you start your Spring Boot application:
mvn spring-boot:run
Spring Boot will:
- Detect the
compose.yamlfile - Start all services defined in the file
- Wait for health checks to pass
- Provide connection details to your application
- Start your application
Disabling Docker Compose
To disable Docker Compose integration (e.g., when running against an external service):
spring.docker.compose.enabled=false
Or set the environment variable:
export SPRING_DOCKER_COMPOSE_ENABLED=false
Custom Compose File Location
If your compose.yaml is in a different location:
spring.docker.compose.file=./docker/compose.yaml