Files
posthog/docker-compose.dev.yml

968 lines
32 KiB
YAML

#
# docker-compose file used ONLY for local development.
# For more info, see:
# https://posthog.com/handbook/engineering/developing-locally
#
# PostHog has sunset support for self-hosted K8s deployments.
# See: https://posthog.com/blog/sunsetting-helm-support-posthog
#
# Profile guidance:
# New optional services should declare `profiles:` directly on the service
# here (see capture, plugins, ingestion-* for examples).
# docker-compose.profiles.yml is a legacy overlay that retroactively gates
# older services; do not add new entries there.
#
services:
proxy:
extends:
file: docker-compose.base.yml
service: proxy
ports:
- 127.0.0.1:8010:8000
extra_hosts:
- 'web:host-gateway'
- 'plugins:host-gateway'
- 'capture:host-gateway'
- 'capture-ai:host-gateway'
- 'capture-logs:host-gateway'
- 'capture-apm-metrics:host-gateway'
- 'replay-capture:host-gateway'
- 'feature-flags:host-gateway'
- 'hypercache-server:host-gateway'
- 'push-api:host-gateway'
environment:
CADDYFILE: |
{
servers {
trusted_proxies static ${CADDY_TRUSTED_PROXIES:-127.0.0.1/32 ::1/128}
}
}
${CADDY_HOST:-http://localhost:8000} {
@replay-capture {
path /s
path /s/*
}
@capture-ai {
path /i/v0/ai
path /i/v0/ai/*
path /i/v1/ai/events
path /i/v1/ai/events/
}
@capture {
path /e
path /e/*
path /i/v0/*
path /i/v1/analytics/events
path /i/v1/analytics/events/
path /batch
path /batch*
path /capture
path /capture*
}
@capture-logs {
path /i/v1/logs
path /i/v1/traces
}
@capture-apm-metrics {
path /i/v1/metrics
path /i/v1/prometheus/write
path /i/v1/prometheus/write/*
}
@flags {
path /flags
path /flags*
# Local evaluation (flag definitions) — mirrors cloud Contour routing to Rust
path /api/feature_flag/local_evaluation
path /api/feature_flag/local_evaluation/
path /api/feature_flag/local_evaluation/*
}
@surveys {
path /surveys
path /surveys/
path /api/surveys
path /api/surveys/
}
@remote-config {
path /array/*
}
@webhooks {
path /public/webhooks
path /public/webhooks/*
path /public/m
path /public/m/*
}
@push-subscriptions {
path /api/push_subscriptions
path /api/push_subscriptions/
}
handle @capture-ai {
reverse_proxy capture-ai:3309
}
handle @capture {
reverse_proxy capture:3307
}
handle @capture-logs {
reverse_proxy capture-logs:4320
}
handle @capture-apm-metrics {
reverse_proxy capture-apm-metrics:4321
}
handle @replay-capture {
reverse_proxy replay-capture:3306
}
handle @flags {
reverse_proxy feature-flags:3001
}
handle @surveys {
reverse_proxy hypercache-server:3002
}
handle @remote-config {
reverse_proxy hypercache-server:3002
}
handle @webhooks {
reverse_proxy plugins:6738
}
handle @push-subscriptions {
reverse_proxy push-api:6750
}
handle {
reverse_proxy web:8000
}
}
capture:
extends:
file: docker-compose.base.yml
service: capture
image: ghcr.io/posthog/posthog/capture:${POSTHOG_CAPTURE_TAG:-master}
restart: on-failure
ports:
- '3307:3000'
depends_on:
kafka:
condition: service_healthy
redis7:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/_liveness']
interval: 5s
timeout: 5s
retries: 24
start_period: 10s
profiles:
- capture
capture-ai:
extends:
file: docker-compose.base.yml
service: capture-ai
image: ghcr.io/posthog/posthog/capture:${POSTHOG_CAPTURE_TAG:-master}
restart: on-failure
ports:
- '3309:3000'
depends_on:
kafka:
condition: service_healthy
redis7:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/_liveness']
interval: 5s
timeout: 5s
retries: 24
start_period: 10s
profiles:
- ingestion
plugins:
extends:
file: docker-compose.base.yml
service: plugins
image: ghcr.io/posthog/posthog-node:${POSTHOG_NODE_TAG:-master}
ports:
- '6738:6738'
environment:
DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_DB_NAME:-posthog}
PERSONS_DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_PERSONS_DB_NAME:-posthog}
# The plugins container runs the CDP rerun worker (default capabilities), which
# requires this. bin/start exports it for local dev; the value below is the default
# for callers (like the E2E CI job) that launch this service without bin/start.
CYCLOTRON_NODE_DATABASE_URL: ${CYCLOTRON_NODE_DATABASE_URL:-postgres://posthog:posthog@db:5432/cyclotron_node}
CLICKHOUSE_DATABASE: ${CLICKHOUSE_DATABASE:-posthog}
# CDP Redis defaults to 127.0.0.1 — must point to the Docker service
CDP_REDIS_HOST: redis7
CDP_VALKEY_HOST: valkey-cluster
CDP_VALKEY_PORT: 6390
# Encryption keys default is only set when NODE_ENV=dev, but the image uses production
ENCRYPTION_SALT_KEYS: '00beef0000beef0000beef0000beef00'
# PersonHog is required for CDP — point at the local gRPC router
PERSONHOG_ADDR: 'personhog-router:50052'
PERSONHOG_ENABLED: 'true'
depends_on:
kafka:
condition: service_started
redis7:
condition: service_healthy
valkey-cluster:
condition: service_healthy
db:
condition: service_healthy
personhog-router:
condition: service_started
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:6738/_ready']
interval: 5s
timeout: 5s
retries: 30
start_period: 15s
profiles:
- ingestion
ingestion-general:
extends:
file: docker-compose.base.yml
service: ingestion-general
image: ghcr.io/posthog/posthog-node:${POSTHOG_NODE_TAG:-master}
ports:
- '6739:6738'
environment:
DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_DB_NAME:-posthog}
PERSONS_DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_PERSONS_DB_NAME:-posthog}
CLICKHOUSE_DATABASE: ${CLICKHOUSE_DATABASE:-posthog}
# The combined-mode AI consumer reads persons through PersonHog
PERSONHOG_ADDR: 'personhog-router:50052'
PERSONHOG_ENABLED: 'true'
depends_on:
kafka:
condition: service_started
redis7:
condition: service_healthy
db:
condition: service_healthy
objectstorage:
# The combined AI consumer's blob store healthchecks the ai-blobs bucket at
# startup, and SeaweedFS creates it asynchronously, so wait for the sentinel.
condition: service_healthy
personhog-router:
condition: service_started
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:6738/_ready']
interval: 5s
timeout: 5s
retries: 30
start_period: 15s
profiles:
- ingestion
ingestion-sessionreplay:
extends:
file: docker-compose.base.yml
service: ingestion-sessionreplay
image: ghcr.io/posthog/posthog-node:${POSTHOG_NODE_TAG:-master}
ports:
- '6740:6738'
environment:
DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_DB_NAME:-posthog}
ENCRYPTION_SALT_KEYS: '00beef0000beef0000beef0000beef00'
depends_on:
kafka:
condition: service_started
redis7:
condition: service_healthy
db:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:6738/_ready']
interval: 5s
timeout: 5s
retries: 30
start_period: 15s
profiles:
- ingestion
recording-api:
extends:
file: docker-compose.base.yml
service: recording-api
image: ghcr.io/posthog/posthog-node:${POSTHOG_NODE_TAG:-master}
ports:
- '6741:6738'
environment:
DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_DB_NAME:-posthog}
CLICKHOUSE_DATABASE: ${CLICKHOUSE_DATABASE:-posthog}
ENCRYPTION_SALT_KEYS: '00beef0000beef0000beef0000beef00'
# The image runs as production, so the in-code dev defaults do not apply. Set both
# secrets to the values Django uses under DEBUG so local calls authenticate and exercise
# the JWT path. These live here rather than in docker-compose.base.yml because hobby
# extends that file, and hobby's Django resolves both secrets to empty, so inheriting
# them there would make recording-api reject every hobby call.
INTERNAL_API_SECRET: 'posthog123'
RECORDING_API_JWT_SECRET: 'dev-recording-api-jwt-secret'
depends_on:
redis7:
condition: service_healthy
db:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:6738/_ready']
interval: 5s
timeout: 5s
retries: 30
start_period: 15s
profiles:
- ingestion
ingestion-error-tracking:
extends:
file: docker-compose.base.yml
service: ingestion-error-tracking
image: ghcr.io/posthog/posthog-node:${POSTHOG_NODE_TAG:-master}
ports:
- '6742:6738'
environment:
DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_DB_NAME:-posthog}
PERSONHOG_ADDR: 'personhog-router:50052'
PERSONHOG_ENABLED: 'true'
depends_on:
kafka:
condition: service_started
redis7:
condition: service_healthy
db:
condition: service_healthy
personhog-router:
condition: service_started
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:6738/_ready']
interval: 5s
timeout: 5s
retries: 30
start_period: 15s
profiles:
- ingestion
ingestion-logs:
extends:
file: docker-compose.base.yml
service: ingestion-logs
image: ghcr.io/posthog/posthog-node:${POSTHOG_NODE_TAG:-master}
ports:
- '6743:6738'
environment:
DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_DB_NAME:-posthog}
depends_on:
kafka:
condition: service_started
redis7:
condition: service_healthy
db:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:6738/_ready']
interval: 5s
timeout: 5s
retries: 30
start_period: 15s
profiles:
- ingestion
ingestion-traces:
extends:
file: docker-compose.base.yml
service: ingestion-traces
image: ghcr.io/posthog/posthog-node:${POSTHOG_NODE_TAG:-master}
ports:
- '6744:6738'
environment:
DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_DB_NAME:-posthog}
depends_on:
kafka:
condition: service_started
redis7:
condition: service_healthy
db:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:6738/_ready']
interval: 5s
timeout: 5s
retries: 30
start_period: 15s
profiles:
- ingestion
browserless:
# Renders heatmap screenshots and image exports — there is no local-browser fallback.
# Optional: docker compose -f docker-compose.dev.yml --profile browserless up -d browserless
# See the HEATMAP_BROWSERLESS_* / BROWSERLESS_* entries in .env.example for the app-side wiring.
image: ghcr.io/browserless/chromium:v2.51.2
restart: on-failure
ports:
- '127.0.0.1:4445:3000'
environment:
TOKEN: dev
LOG_LEVEL: warn
DEBUG: '-*'
profiles:
- browserless
db:
extends:
file: docker-compose.base.yml
service: db
ports:
- '5432:5432'
volumes:
- postgres-15-data:/var/lib/postgresql/data
# something in the django app when running in dev mode
# (maybe only in Pycharm) keeps many idle transactions open
# and eventually kills postgres, these settings aim to stop that happening.
# They are only for DEV and should not be used in production.
command: postgres -c max_connections=1000 -c idle_in_transaction_session_timeout=300000 -c max_prepared_transactions=10
redis7:
extends:
file: docker-compose.base.yml
service: redis7
ports:
- '6379:6379'
valkey-cluster:
image: valkey/valkey:8.1-alpine
restart: on-failure
ports:
- '127.0.0.1:6390:6390'
command:
- /bin/sh
- -ec
- |
# 6390 inside the container as well as on the host, so the port CLUSTER SLOTS
# announces is right for both. It announces no address, which every cluster
# client reads as "the one you reached me on", so a host client stays on
# 127.0.0.1 and a container client stays on valkey-cluster. Announcing an
# address instead would name one of those two and break the other.
valkey-server --port 6390 --cluster-enabled yes --cluster-config-file /tmp/nodes.conf --cluster-node-timeout 5000 &
pid=$$!
until valkey-cli -p 6390 ping >/dev/null 2>&1; do sleep 0.1; done
valkey-cli -p 6390 cluster addslots $$(seq 0 16383)
wait $$pid
healthcheck:
test:
[
'CMD-SHELL',
'valkey-cli -p 6390 cluster info | grep -q cluster_state:ok && test "$$(valkey-cli -p 6390 cluster info | sed -n "s/cluster_slots_assigned://p" | tr -d "\r")" = 16384',
]
interval: 2s
timeout: 3s
retries: 15
start_period: 5s
redis-cluster:
image: redis:7.2
restart: on-failure
ports:
- '127.0.0.1:6399:6379'
command: >
bash -c "
redis-server
--port 6379
--cluster-enabled yes
--cluster-config-file /data/nodes.conf
--cluster-node-timeout 5000
--cluster-announce-ip 127.0.0.1
--cluster-announce-port 6399
--appendonly yes &
sleep 1 &&
redis-cli -p 6379 cluster addslots $$(seq 0 16383) &&
tail -f /dev/null
"
volumes:
- redis-cluster-data:/data
healthcheck:
test: ['CMD', 'redis-cli', '-p', '6379', 'cluster', 'info']
interval: 2s
timeout: 3s
retries: 10
flower:
extends:
file: docker-compose.base.yml
service: flower
ports:
- '5555:5555'
clickhouse:
extends:
file: docker-compose.base.yml
service: clickhouse
hostname: clickhouse
# ClickHouse writes ~1 GB/hour in dev and json-file driver has no default rotation
logging:
driver: json-file
options:
max-size: '50m'
max-file: '3'
# Development performance optimizations
mem_limit: 8g
cpus: 2
environment:
- AWS_ACCESS_KEY_ID=object_storage_root_user
- AWS_SECRET_ACCESS_KEY=object_storage_root_password
- CLICKHOUSE_SKIP_USER_SETUP=1
ports:
- '8123:8123'
- '8443:8443'
- '9000:9000'
- '9440:9440'
- '9009:9009'
volumes:
- ./posthog/idl:/idl
- ./docker/clickhouse/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
- ./docker/clickhouse/config.xml:/etc/clickhouse-server/config.xml
- ./docker/clickhouse/config.d/default.xml:/etc/clickhouse-server/config.d/default.xml
- ./docker/clickhouse/config.d/dev-memory.xml:/etc/clickhouse-server/config.d/dev-memory.xml
- ./docker/clickhouse/users-dev.xml:/etc/clickhouse-server/users.xml
- ./docker/clickhouse/user_defined_function.xml:/etc/clickhouse-server/user_defined_function.xml
- ./posthog/user_scripts:/var/lib/clickhouse/user_scripts
- clickhouse-data:/var/lib/clickhouse
extra_hosts:
- 'host.docker.internal:host-gateway'
depends_on:
- kafka
- zookeeper
zookeeper:
extends:
file: docker-compose.base.yml
service: zookeeper
ports:
- '2181:2181'
# With persistent volumes, snapshots and txn logs accumulate forever unless
# autopurge is on (the image default disables it). Matches hobby.
environment:
ZOO_AUTOPURGE_PURGEINTERVAL: 1
ZOO_AUTOPURGE_SNAPRETAINCOUNT: 3
volumes:
- zookeeper-datalog:/datalog
- zookeeper-data:/data
- zookeeper-logs:/logs
kafka:
extends:
file: docker-compose.base.yml
service: kafka
ports:
- '9092:9092'
depends_on:
- zookeeper
kafka-init:
image: docker.io/redpandadata/redpanda:v25.1.9
entrypoint: /bin/sh
restart: 'no'
command:
- -c
- |
set -x
# Redpanda auto_create_topics_enabled=true only fires on producer-first
# writes. Consumer-only services (e.g. embedding-worker) error on missing
# topics, so we pre-create them here. Idempotent — re-running is safe.
TIMEOUT=60
ELAPSED=0
until rpk topic list --brokers kafka:9092 2>/dev/null; do
echo "Waiting for Kafka broker... (elapsed: ${ELAPSED}s)"
sleep 2
ELAPSED=$((ELAPSED + 2))
if [ $ELAPSED -ge $TIMEOUT ]; then
echo "Timeout waiting for Kafka broker after ${TIMEOUT}s"
exit 1
fi
done
# The topic list is docker/kafka/topics.txt, mounted below. It is a
# shared file rather than a literal here so a test can check it against the
# Kafka tables in schema.py; that header explains what needs pre-creating.
TOPICS=$$(grep -vE '^[[:space:]]*#|^[[:space:]]*$$' /topics.txt)
EXISTING=$$(rpk topic list --brokers kafka:9092 | awk '{print $$1}')
for topic in $$TOPICS; do
if rpk topic create "$$topic" --brokers kafka:9092 -p 1 -r 1 2>&1; then
echo "Topic $$topic created"
elif echo "$$EXISTING" | grep -qx "$$topic"; then
echo "Topic $$topic already exists"
else
echo "Failed to create topic $$topic"
exit 1
fi
done
volumes:
- ./docker/kafka/topics.txt:/topics.txt:ro
depends_on:
kafka:
condition: service_healthy
kafka_ui:
extends:
file: docker-compose.base.yml
service: kafka_ui
ports:
- '9093:8080'
environment:
SERVER_MAX_HTTP_REQUEST_HEADER_SIZE: 65536
depends_on:
- kafka
objectstorage:
extends:
file: docker-compose.base.yml
service: objectstorage
ports:
- '19000:19000'
- '19001:19001'
# Named volume from the SeaweedFS swap; the old MinIO volume is left in place
# because SeaweedFS cannot read its on-disk format.
volumes:
- objectstorage-data:/data
objectstorage-azure:
extends:
file: docker-compose.base.yml
service: objectstorage-azure
ports:
- '10000:10000'
maildev:
extends:
file: docker-compose.base.yml
service: maildev
ports:
- '1080:1080'
- '1025:1025'
webhook-tester:
image: tarampampam/webhook-tester:2.2.6
restart: on-failure
ports:
- '2080:8080'
environment:
- AUTO_CREATE_SESSIONS=true
personhog-replica:
extends:
file: docker-compose.base.yml
service: personhog-replica
environment:
PRIMARY_DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_PERSONS_DB_NAME:-posthog}
depends_on:
db:
condition: service_healthy
profiles:
- ingestion
personhog-router:
extends:
file: docker-compose.base.yml
service: personhog-router
ports:
- '50052:50052'
depends_on:
personhog-replica:
condition: service_started
profiles:
- ingestion
personhog-router-leader:
extends:
file: docker-compose.base.yml
service: personhog-router-leader
ports:
- '50054:50054'
depends_on:
etcd:
condition: service_healthy
personhog-replica:
condition: service_started
profiles:
- ingestion
personhog-leader:
extends:
file: docker-compose.base.yml
service: personhog-leader
environment:
FALLBACK_DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_PERSONS_DB_NAME:-posthog}
depends_on:
etcd:
condition: service_healthy
db:
condition: service_healthy
kafka:
condition: service_started
personhog-etcd-init:
condition: service_completed_successfully
profiles:
- ingestion
personhog-writer:
extends:
file: docker-compose.base.yml
service: personhog-writer
environment:
DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_PERSONS_DB_NAME:-posthog}
depends_on:
etcd:
condition: service_healthy
db:
condition: service_healthy
kafka:
condition: service_started
personhog-etcd-init:
condition: service_completed_successfully
profiles:
- ingestion
personhog-identity:
extends:
file: docker-compose.base.yml
service: personhog-identity
environment:
PRIMARY_DATABASE_URL: postgres://posthog:posthog@db:5432/${POSTHOG_PERSONS_DB_NAME:-posthog}
ports:
- '50055:50055'
depends_on:
db:
condition: service_healthy
personhog-router-leader:
condition: service_started
profiles:
- ingestion
# Seeds the changelog config the personhog services read at boot;
# idempotent, and the same key bin/mprocs.yaml writes for hogli runs.
personhog-etcd-init:
image: quay.io/coreos/etcd:v3.6.8
restart: 'no'
entrypoint:
[
'etcdctl',
'--endpoints=http://etcd:2379',
'put',
'/personhog/config/changelog',
'{"topic":"personhog_updates","partitions":4,"epoch":1,"writer_group":"personhog-writer","draining":[]}',
]
depends_on:
etcd:
condition: service_healthy
profiles:
- ingestion
feature-flags:
extends:
file: docker-compose.base.yml
service: feature-flags
depends_on:
redis7:
condition: service_healthy
db:
condition: service_healthy
environment:
FLAGS_REDIS_URL: 'redis://redis7:6379/1'
# The /flags/definitions reader stays on shared Redis unless
# FLAG_DEFINITIONS_DEDICATED_REDIS_ENABLED is set.
REDIS_COMPRESSION_ENABLED: 'true'
INTERNAL_REQUEST_TOKEN: 'dev-internal-token'
usage-ingestion:
extends:
file: docker-compose.base.yml
service: usage-ingestion
ports:
- '7143:7143'
- '7144:7144'
depends_on:
db:
condition: service_healthy
kafka:
condition: service_healthy
valkey-cluster:
condition: service_healthy
environment:
USAGE_INGESTION_REDIS_URL: 'redis://valkey-cluster:6390'
# Keeps a bare `up` from building an image that is not published yet.
profiles:
- ingestion
# Temporal containers
elasticsearch:
extends:
file: docker-compose.base.yml
service: elasticsearch
expose:
- 9200
# OpenSearch (LLM trace reverse index). 9201 to avoid Elasticsearch's 9200.
opensearch:
extends:
file: docker-compose.base.yml
service: opensearch
ports:
- '127.0.0.1:9201:9200'
profiles: [opensearch]
opensearch-dashboards:
extends:
file: docker-compose.base.yml
service: opensearch-dashboards
ports:
- '127.0.0.1:5601:5601'
profiles: [opensearch]
opensearch-init:
image: curlimages/curl:8.10.1
depends_on:
opensearch:
condition: service_healthy
restart: 'no'
volumes:
- ./products/ai_observability/opensearch:/work:ro
entrypoint: ['sh', '/work/init.sh']
profiles: [opensearch]
temporal:
extends:
file: docker-compose.base.yml
service: temporal
ports:
- 7233:7233
volumes:
- ./docker/temporal/dynamicconfig:/etc/temporal/config/dynamicconfig
temporal-admin-tools:
extends:
file: docker-compose.base.yml
service: temporal-admin-tools
depends_on:
- temporal
temporal-ui:
extends:
file: docker-compose.base.yml
service: temporal-ui
ports:
- 8081:8080
depends_on:
temporal:
condition: service_started
db:
condition: service_healthy
otel-collector:
extends:
file: docker-compose.base.yml
service: otel-collector
container_name: otel-collector-local
ports:
- '4317:4317' # OTLP gRPC receiver
- '4318:4318' # OTLP HTTP receiver
- '13133:13133' # health_check extension
- '55679:55679' # zpages extension
volumes:
- ./otel-collector-config.dev.yaml:/etc/otel-collector-config.yaml
environment:
# Used by otel-collector-config.dev.yaml to scope container log
# collection to this compose project only.
COMPOSE_PROJECT: posthog
extra_hosts:
- 'host.docker.internal:host-gateway'
depends_on:
- jaeger
jaeger:
extends:
file: docker-compose.base.yml
service: jaeger
container_name: jaeger-local
ports:
- '16686:16686' # Jaeger UI
- '14268:14268' # jaeger.thrift
- '14250:14250' # model.proto
dynamodb:
extends:
file: docker-compose.base.yml
service: dynamodb
profiles: [dynamodb]
container_name: '${DYNAMODB_DOCKER_NAME:-dynamodb-main}'
ports:
# Not 8000 (the Django dev server) and not 18000, which the eval harness binds for its
# live server, where sharing the port fails `hogli evals` on Linux with the stack up.
- '127.0.0.1:18010:8000'
seaweedfs:
extends:
file: docker-compose.base.yml
service: seaweedfs
container_name: '${SEAWEEDFS_DOCKER_NAME:-seaweedfs-main}'
command: server -s3 -s3.port=8333 -filer -dir=/data
ports:
- '127.0.0.1:8333:8333' # S3 API
- '127.0.0.1:9333:9333' # Master server
- '127.0.0.1:8888:8888' # SeaweedFS Filer UI
volumes:
- 'seaweedfs-data:/data'
duckgres:
extends:
file: docker-compose.base.yml
service: duckgres
profiles: ['duckgres']
ports:
- '15432:15432'
etcd:
image: quay.io/coreos/etcd:v3.6.8
restart: on-failure
environment:
ETCD_NAME: etcd0
ETCD_ADVERTISE_CLIENT_URLS: http://etcd:2379
ETCD_LISTEN_CLIENT_URLS: http://0.0.0.0:2379
ports:
- '127.0.0.1:2379:2379'
healthcheck:
test: ['CMD', 'etcdctl', 'endpoint', 'health']
interval: 5s
timeout: 5s
retries: 10
networks:
otel_network:
driver: bridge
volumes:
postgres-15-data:
redis-cluster-data:
redpanda-data:
seaweedfs-data:
duckgres-data:
objectstorage-data:
clickhouse-data:
zookeeper-data:
zookeeper-datalog:
zookeeper-logs: