d05f1a7398
Replaces Remix compiler with the Vite plugin. The Express server (cluster, socket.io, ws) and the Docker image contract are unchanged.
263 lines
8.6 KiB
YAML
263 lines
8.6 KiB
YAML
# Core local-dev stack: the minimum a contributor needs to boot the webapp.
|
|
# For optional services (object store, observability, HTTP/2 proxy, chaos
|
|
# tooling, ClickHouse UI, extra electric shard) see ./docker-compose.extras.yml
|
|
# and the `pnpm run docker:full` script.
|
|
#
|
|
# Every host port is overridable via env vars from the root `.env` so multiple
|
|
# instances (worktrees, branch experiments) can run side by side. See the
|
|
# "Multiple instances" block in `.env.example` for the full set of knobs.
|
|
name: triggerdotdev-docker
|
|
|
|
volumes:
|
|
database-data:
|
|
database-data-alt:
|
|
database-runops-data:
|
|
database-replica-data:
|
|
redis-data:
|
|
minio-data:
|
|
clickhouse-data:
|
|
clickhouse-logs:
|
|
|
|
networks:
|
|
app_network:
|
|
external: false
|
|
|
|
services:
|
|
database:
|
|
container_name: ${CONTAINER_PREFIX:-}database
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile.postgres
|
|
restart: always
|
|
volumes:
|
|
- ${DB_VOLUME:-database-data}:/var/lib/postgresql/data/
|
|
environment:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: postgres
|
|
networks:
|
|
- app_network
|
|
ports:
|
|
- "${POSTGRES_HOST_PORT:-5432}:5432"
|
|
command:
|
|
- -c
|
|
- listen_addresses=*
|
|
- -c
|
|
- wal_level=logical
|
|
- -c
|
|
- shared_preload_libraries=pg_partman_bgw
|
|
# The webapp opens ~50 pooled connections per instance and Electric another
|
|
# ~40, so the default 100 is exhausted by one webapp + Electric alone. Raise
|
|
# it so multiple instances / load tests have headroom.
|
|
- -c
|
|
- max_connections=500
|
|
|
|
# Opt-in NEW run-ops database, PG17 (the `database` above is PG14) — a separate cluster
|
|
# so the run-ops split's distinct-DB sentinel passes. Start with:
|
|
# COMPOSE_PROFILES=runops pnpm run docker
|
|
database-runops:
|
|
container_name: ${CONTAINER_PREFIX:-}database-runops
|
|
profiles: ["runops"]
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile.postgres17
|
|
restart: always
|
|
volumes:
|
|
- ${DB_RUNOPS_VOLUME:-database-runops-data}:/var/lib/postgresql/data/
|
|
environment:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: postgres
|
|
networks:
|
|
- app_network
|
|
ports:
|
|
- "${POSTGRES_RUNOPS_HOST_PORT:-5434}:5432"
|
|
command:
|
|
- -c
|
|
- listen_addresses=*
|
|
- -c
|
|
- wal_level=logical
|
|
- -c
|
|
- shared_preload_libraries=pg_partman_bgw
|
|
- -c
|
|
- max_connections=500
|
|
|
|
# Opt-in streaming read replica with configurable apply lag — a dial-a-lag rig for
|
|
# testing replica-race behavior (e.g. the realtime read-your-writes gate) locally.
|
|
# Start with: COMPOSE_PROFILES=replica pnpm run docker
|
|
# One-time primary prep (allows replication connections; additive, survives restarts):
|
|
# docker exec database bash -c 'grep -q "host replication" "$PGDATA/pg_hba.conf" || echo "host replication all all md5" >> "$PGDATA/pg_hba.conf"'
|
|
# docker exec database psql -U postgres -c "SELECT pg_reload_conf()"
|
|
# Then point the webapp at it: DATABASE_READ_REPLICA_URL=postgresql://postgres:postgres@localhost:5433/postgres
|
|
# Tune the lag via REPLICA_APPLY_DELAY (default 20ms ~ realistic prod lag; crank to 150ms/2s to
|
|
# shake out replica races). Wipe database-replica-data to re-init.
|
|
database-replica:
|
|
container_name: ${CONTAINER_PREFIX:-}database-replica
|
|
profiles: ["replica"]
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile.postgres
|
|
restart: always
|
|
depends_on:
|
|
- database
|
|
volumes:
|
|
- ${DB_REPLICA_VOLUME:-database-replica-data}:/var/lib/postgresql/data/
|
|
environment:
|
|
PGPASSWORD: postgres
|
|
REPLICA_APPLY_DELAY: ${REPLICA_APPLY_DELAY:-20ms}
|
|
networks:
|
|
- app_network
|
|
ports:
|
|
- "${POSTGRES_REPLICA_HOST_PORT:-5433}:5432"
|
|
entrypoint: ["bash", "-c"]
|
|
command:
|
|
- |
|
|
set -e
|
|
if [ ! -s "$$PGDATA/PG_VERSION" ]; then
|
|
echo "initializing streaming replica from 'database'..."
|
|
mkdir -p "$$PGDATA"
|
|
chown postgres:postgres "$$PGDATA"
|
|
chmod 0700 "$$PGDATA"
|
|
until gosu postgres pg_basebackup -h database -U postgres -D "$$PGDATA" -Fp -Xs -R; do
|
|
echo "primary not ready for replication (did you run the one-time pg_hba prep above?); retrying..."
|
|
rm -rf "$$PGDATA"/* 2>/dev/null || true
|
|
sleep 2
|
|
done
|
|
fi
|
|
# max_connections must be >= the primary's (hot-standby requirement).
|
|
exec docker-entrypoint.sh postgres -c hot_standby=on -c max_connections=500 -c "recovery_min_apply_delay=$$REPLICA_APPLY_DELAY"
|
|
|
|
redis:
|
|
container_name: ${CONTAINER_PREFIX:-}redis
|
|
image: redis:7@sha256:3e1b24a1a8f24ff926b15e5ace8c38a03e5657fb66e1fc7e5188e315aa5fa094
|
|
restart: always
|
|
volumes:
|
|
- redis-data:/data
|
|
networks:
|
|
- app_network
|
|
ports:
|
|
- "${REDIS_HOST_PORT:-6379}:6379"
|
|
|
|
# S3-compatible API for the local object store (large payloads / packet
|
|
# offload). Host :${MINIO_API_HOST_PORT:-9005} = S3 API,
|
|
# host :${MINIO_CONSOLE_HOST_PORT:-9006} = web console. The webapp only
|
|
# routes to it when the OBJECT_STORE_* env vars are set (see .env.example).
|
|
minio:
|
|
container_name: ${CONTAINER_PREFIX:-}minio
|
|
image: minio/minio:latest@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
|
restart: always
|
|
command: server /data --console-address ":9001"
|
|
environment:
|
|
MINIO_ROOT_USER: minioadmin
|
|
MINIO_ROOT_PASSWORD: minioadmin
|
|
volumes:
|
|
- minio-data:/data
|
|
ports:
|
|
- "${MINIO_API_HOST_PORT:-9005}:9000"
|
|
- "${MINIO_CONSOLE_HOST_PORT:-9006}:9001"
|
|
networks:
|
|
- app_network
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
start_period: 5s
|
|
|
|
minio-init:
|
|
image: minio/mc:latest@sha256:a7fe349ef4bd8521fb8497f55c6042871b2ae640607cf99d9bede5e9bdf11727
|
|
depends_on:
|
|
minio:
|
|
condition: service_healthy
|
|
networks:
|
|
- app_network
|
|
entrypoint: /bin/sh
|
|
command:
|
|
- -c
|
|
- |
|
|
mc alias set local http://minio:9000 minioadmin minioadmin
|
|
mc mb -p local/packets || true
|
|
restart: "no"
|
|
|
|
electric:
|
|
container_name: ${CONTAINER_PREFIX:-}electric
|
|
image: electricsql/electric:1.2.4@sha256:20da3d0b0e74926c5623392db67fd56698b9e374c4aeb6cb5cadeb8fea171c36
|
|
restart: always
|
|
environment:
|
|
DATABASE_URL: postgresql://postgres:postgres@database:5432/postgres?sslmode=disable
|
|
ELECTRIC_INSECURE: true
|
|
ELECTRIC_ENABLE_INTEGRATION_TESTING: true
|
|
networks:
|
|
- app_network
|
|
ports:
|
|
- "${ELECTRIC_HOST_PORT:-3060}:3000"
|
|
depends_on:
|
|
- database
|
|
|
|
clickhouse:
|
|
image: clickhouse/clickhouse-server:26.2.19.43@sha256:c2f2605585899d5103a0447daadbc0005f362200d5f0fcca7f40db3ca0dd36dd
|
|
restart: always
|
|
container_name: ${CONTAINER_PREFIX:-}clickhouse
|
|
ulimits:
|
|
nofile:
|
|
soft: 262144
|
|
hard: 262144
|
|
environment:
|
|
CLICKHOUSE_USER: default
|
|
CLICKHOUSE_PASSWORD: password
|
|
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
|
|
ports:
|
|
- "${CLICKHOUSE_HTTP_HOST_PORT:-8123}:8123"
|
|
- "${CLICKHOUSE_TCP_HOST_PORT:-9000}:9000"
|
|
volumes:
|
|
- clickhouse-data:/var/lib/clickhouse
|
|
- clickhouse-logs:/var/log/clickhouse-server
|
|
- ./config/clickhouse-disable-system-logs.xml:/etc/clickhouse-server/config.d/disable-system-logs.xml:ro
|
|
networks:
|
|
- app_network
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD",
|
|
"clickhouse-client",
|
|
"--host",
|
|
"localhost",
|
|
"--port",
|
|
"9000",
|
|
"--user",
|
|
"default",
|
|
"--password",
|
|
"password",
|
|
"--query",
|
|
"SELECT 1",
|
|
]
|
|
interval: 3s
|
|
timeout: 5s
|
|
retries: 5
|
|
start_period: 10s
|
|
|
|
clickhouse_migrator:
|
|
build:
|
|
context: ../internal-packages/clickhouse
|
|
dockerfile: ./Dockerfile
|
|
depends_on:
|
|
clickhouse:
|
|
condition: service_healthy
|
|
networks:
|
|
- app_network
|
|
command: ["goose", "${GOOSE_COMMAND:-up}"]
|
|
|
|
# s2-lite: open-source S2 (https://s2.dev) for local realtime streams v2.
|
|
# The image is distroless (no shell), so a `wget` / `curl` healthcheck
|
|
# always reports unhealthy even when the API is responding. No other
|
|
# service depends on this one, so the healthcheck is omitted.
|
|
s2:
|
|
image: ghcr.io/s2-streamstore/s2:latest@sha256:d6ded5ca7dd619fa7c946f06e39a98f9c95c6883c8bb884e5eaa129f232c920c
|
|
command: ["lite", "--init-file", "/s2-spec.json"]
|
|
volumes:
|
|
- ./config/s2-spec.json:/s2-spec.json:ro
|
|
ports:
|
|
- "${S2_HOST_PORT:-4566}:80"
|
|
networks:
|
|
- app_network
|