-
Notifications
You must be signed in to change notification settings - Fork 63
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
107 lines (104 loc) · 5.35 KB
/
Copy pathdocker-compose.yml
File metadata and controls
107 lines (104 loc) · 5.35 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
99
100
101
102
103
104
105
106
107
# restheart-mongo sample compose. RESTHeart 9.x + MongoDB 7 on a
# fixed subnet, every name env-driven so multiple matrix cells
# can run in parallel on the same docker daemon.
services:
restheart:
build:
context: .
dockerfile: Dockerfile
container_name: ${RESTHEART_APP_CONTAINER:-restheart_app}
init: true
stop_grace_period: 5s
ports:
- "${RESTHEART_APP_PORT:-8080}:8080"
environment:
# RHO is RESTHeart's runtime config-override syntax:
# key->value pairs separated by ';'
# We override the default mongo URL (which the upstream image
# points at host.docker.internal — irrelevant in compose),
# explicitly bind /http-listener/host to 0.0.0.0 (without it
# the upstream image binds localhost and is unreachable from
# the host port mapping), AND pin /jwtConfigProvider/key to
# a fixed secret. The default `key: null` makes RESTHeart
# generate a fresh random HS256 secret on every container
# start. Recorded JWT bearers carry an HS256 signature over
# the payload using that secret, so a fresh-container replay
# phase rejects the recorded bearer with 401 even though
# --freezeTime keeps `exp` valid. Pinning the secret keeps
# the bearer signature verifiable across record→replay
# container restarts (deterministic key, deterministic JWT).
RHO: '/mclient/connection-string->"mongodb://${RESTHEART_MONGO_IP:-172.36.0.10}:27017";/http-listener/host->"0.0.0.0";/core/log-level->"INFO";/jwtConfigProvider/key->"keploy-fixed-jwt-secret-for-deterministic-recordings";/mongoAclAuthorizer/cache-enabled->false;/graphql/app-cache-enabled->false'
# Bound RESTHeart's JVM heap. RESTHeart 9.x's default uses
# `MaxRAMPercentage=25` of cgroup memory, which on a typical
# Woodpecker runner cgroup (~8GB) lands ~2GB heap. With three
# restheart matrix cells running concurrent on the same
# runner alongside parse-server / umami / doccano cells, the
# total memory pressure triggers cgroup OOM and the kernel
# SIGKILLs lighter processes (bash, curl) mid-bootstrap —
# observed in keploy/enterprise pipeline 3721/26 (cell
# record-stable-replay-pr) where `flow.sh bootstrap` got
# killed (exit 137) right after RESTHeart came up. Capping
# heap at 512m keeps each cell's footprint under ~700MB
# (heap + native + mongo) so the runner can host all three
# restheart cells plus the other lanes' cells in parallel.
# 512m is comfortable for the record/replay workload (peak
# observed at ~280MB in single-cell local runs).
JAVA_TOOL_OPTIONS: "-Xms128m -Xmx512m"
# Note on /mongoAclAuthorizer/cache-enabled->false in RHO:
# RESTHeart's mongoAclAuthorizer caches ACL rules with a 5s
# TTL backed by Caffeine, which uses System.nanoTime() to
# measure expiry. When the lane runs `keploy test --freezeTime`,
# the LD_PRELOADed clock-shim intercepts clock_gettime/
# gettimeofday — and Caffeine's nanoTime ticker is also
# frozen — so the cache TTL never expires. flow.sh's `sleep 6`
# between an `acl` rule POST and the writer-permission test
# works at record time (the wall clock advances and the cache
# reloads), but at replay the cache stays loaded with whatever
# state it had at the first request and never picks up the
# newly-POSTed rule. Result: writer gets 403 at replay
# despite recorded 200. Disabling the cache makes ACL rules
# read-through from mongo on every request — small perf cost,
# but eliminates the time-freeze x cache-ttl interaction.
#
# Note on /graphql/app-cache-enabled->false in RHO:
# RESTHeart's GraphQL service caches gql-apps app definitions with a
# 60s time-to-revalidate (app-cache-ttr, Caffeine, nanoTime ticker) —
# the SAME time-freeze x cache-ttl interaction as the ACL cache above.
# flow.sh POSTs a "halpeople" GraphQL app to gql-apps and then fires
# POST /graphql/halpeople queries. At record the wall clock advances,
# so the app cache revalidates (re-reading gql-apps) at TTR
# boundaries; under `keploy test --freezeTime` the ticker is frozen so
# the cache never revalidates, producing a DIFFERENT number/order of
# `find gql-apps` mongo queries than were recorded. The unmatched
# find has no recorded mock -> keploy's mongo proxy closes the socket
# -> RESTHeart returns 500 (MongoSocketReadException) instead of the
# recorded response (the post-graphql-halpeople flakiness). Disabling
# the app cache makes gql-apps read-through on every request, so the
# mongo query stream is identical at record and replay.
depends_on:
mongo:
condition: service_healthy
networks:
- restheart-net
mongo:
image: mongo:7
container_name: ${RESTHEART_MONGO_CONTAINER:-restheart_mongo}
stop_grace_period: 5s
healthcheck:
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
interval: 5s
timeout: 5s
retries: 20
volumes:
- restheart-mongo-data:/data/db
networks:
restheart-net:
ipv4_address: ${RESTHEART_MONGO_IP:-172.36.0.10}
networks:
restheart-net:
driver: bridge
ipam:
config:
- subnet: ${RESTHEART_NETWORK_SUBNET:-172.36.0.0/24}
volumes:
restheart-mongo-data: