Files
agenticCode/docker-compose.yml
Ingo Schnabel 10971915e9 Typescript
2026-09-23 08:15:53 +02:00

114 lines
6.2 KiB
YAML

services:
neo4j:
image: neo4j:5
container_name: agenticcode-neo4j
ports:
- "7474:7474"
- "7687:7687"
environment:
NEO4J_AUTH: neo4j/agenticcode
# Memory caps. Without them the JVM sizes its heap ergonomically at 25% of host RAM
# (~7.8 GiB here) and never gives it back: measured 6.17 GiB still held one hour after a
# deep refresh of upms had finished, at <1% CPU. The cap is what forces the JVM to
# collect rather than commit.
NEO4J_server_memory_heap_max__size: "2G"
NEO4J_server_memory_heap_initial__size: "512M"
# 512M -> 1G -> 3G -> 2G. The store has grown to 2.4 GB (1.2 GB of it range indexes), so 1G
# covered only ~42% of it. 2G covers nearly all of it; the 2.5 GB of transaction logs are
# deliberately not counted, Neo4j does not keep them here. Both sizes were measured on a deep
# refresh of upms: 1G = 552 s, 3G = 519 s, 2G = 517 s. The whole gain is already had at 2G, so
# the third gigabyte stays with the host (a 4 GB VirtualBox guest runs alongside).
#
# The gain is ~6% and modest on purpose to record why: `directio` is false, so Neo4j reads
# through the OS file cache and the store is cached twice. Block I/O across two whole refresh
# runs was 237 MB read against a 2.4 GB store — there was never disk I/O to save. A cache miss
# costs a read() syscall plus a copy, not a seek, and 6% is what removing those is worth. On a
# host whose file cache could NOT hold the store, the same setting would matter far more — so
# treat these numbers as this machine's data points, not as a recommendation.
# Community Edition cannot pre-warm the cache: the first refresh after a restart runs cold
# (540 s here) and is not a fair measurement.
NEO4J_server_memory_pagecache_size: "2G"
# Return committed-but-unused heap to the OS while idle instead of sitting on it. Without this
# the JVM held everything it had ever needed: 6.17 GiB an hour after a refresh had finished.
NEO4J_server_jvm_additional: "-XX:G1PeriodicGCInterval=300000"
# Hard ceiling: heap 2G + pagecache 2G + metaspace, direct buffers and GC overhead.
# Raised 4g -> 5g after a verification run peaked at exactly 4096 of 4096 MB — no OOM-kill, but
# zero reserve. An OOM-kill mid-refresh leaves the graph half-updated, which is far worse than a
# spare GB. This follows the page cache: Neo4j's own rule of thumb is heap + page cache + ~1G, so
# 2G of cache means 6g here — 1G of reserve, not generosity. Do not raise the page cache without
# raising this too.
mem_limit: 6g
volumes:
- neo4j-data:/data
healthcheck:
test: [ "CMD-SHELL", "cypher-shell -u neo4j -p agenticcode 'RETURN 1' || exit 1" ]
interval: 5s
timeout: 5s
retries: 20
start_period: 30s
ac-code-server:
build:
# Repository root, not ./ac-code-server: the image also carries the TypeScript sidecar from
# ac-parser-typescript/sidecar (item 192). The root .dockerignore limits what is sent.
context: .
dockerfile: ac-code-server/src/main/docker/Dockerfile.jvm
container_name: agenticcode-server
ports:
- "8787:8787"
environment:
NEO4J_URI: bolt://neo4j:7687
NEO4J_USER: neo4j
NEO4J_PASSWORD: agenticcode
# JDK_JAVA_OPTIONS (not JAVA_OPTS) — the entrypoint is `java -jar`, which expands no shell
# variable; the JVM reads this one by itself. Both settings must live here: a value set in
# compose replaces the image's, it does not append, so the log-manager property would be
# silently dropped if it were left in the Dockerfile.
#
# -Xmx2500m. Ergonomics would allow 7956 MB, and the process then kept 4.91 GiB resident an
# hour after a refresh had ended. Sizing history, because the first cap was too tight: a deep
# *refresh* peaked at 1593 MB, which suggested 2 GB — but a `project recreate --deep` (heavier:
# ingests from empty) then peaked at 1924 MB, i.e. 94% of that cap. 2500m restores ~25% headroom
# while keeping nearly all of the reduction.
# G1PeriodicGCInterval returns committed-but-unused heap to the OS while idle.
JDK_JAVA_OPTIONS: >-
-Xmx2500m
-XX:G1PeriodicGCInterval=300000
-Djava.util.logging.manager=org.jboss.logmanager.LogManager
# Heap 2.5G + metaspace/code cache/direct buffers. Measured RSS peak was 3472 MB against a 3 GB
# heap cap, i.e. ~1.9 GB non-heap. Item 192 adds the TypeScript sidecar, a Node process the JVM
# runs per npm workspace during a deep pass: measured ~0.75 GB RSS per workspace, capped at
# --max-old-space-size=1024 and run before the JVM's own persist/enrichment peak — so 4g would
# have been tight only if the two peaks coincided; 5g leaves room for that case.
mem_limit: 5g
volumes:
# Mounted at the same absolute host path so project roots registered via
# the API (which store absolute host paths) resolve inside the container too.
# One entry per registered project root (GET /api/projects) — add a line
# here whenever a new project root is registered outside this repo.
- /home/ingo/deve/agenticCode:/home/ingo/deve/agenticCode:ro
- /home/ingo/deve/uniqa/uniqa-upms-app:/home/ingo/deve/uniqa/uniqa-upms-app:ro
- /home/ingo/deve/uniqa/pur-sources/backend:/home/ingo/deve/uniqa/pur-sources/backend:ro
# Item 192: the pur frontend (project `purfe`, language typescript). Read-only like the others;
# the sidecar runs with noEmit and reads the frontend's own node_modules for library typings.
- /home/ingo/deve/uniqa/pur-sources/frontend:/home/ingo/deve/uniqa/pur-sources/frontend:ro
- /home/ingo/deve/tools/conqat/system/src/250401_UMPS/src/pur-analysis/pur-legacy:/home/ingo/deve/tools/conqat/system/src/250401_UMPS/src/pur-analysis/pur-legacy:ro
depends_on:
neo4j:
condition: service_healthy
restart: unless-stopped
ac-ui:
build:
context: ./ac-ui
dockerfile: Dockerfile
container_name: agenticcode-ui
ports:
- "5174:80"
depends_on:
- ac-code-server
restart: unless-stopped
volumes:
neo4j-data: