docker-compose.prod.yml
Rama main · réplica de lectura del repositorio original.
# Reference production compose stack for the EDR server + MySQL.
# Distinct from docker-compose.yml (dev MySQL only). Full setup +
# secret-file generation documented in docker-compose.prod.README.md.
# Boot shortcut:
#
# docker compose -f docker-compose.prod.yml up -d
#
# The server image is pulled from ghcr.io/rawtrail/rawtrail-server; a local
# build uses the docker-compose.prod.build.yml override for smoke tests and
# air-gapped sites.
services:
mysql:
image: mysql:8.4.9@sha256:c36050afdca850f23cef85703f84c7531a5ae155a11b5ee1c60acb09937c4084
restart: unless-stopped
environment:
# MySQL 8.4 reads these _FILE variants natively. Avoids root password in
# any compose env block or docker inspect output.
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root
MYSQL_DATABASE: edr
volumes:
- edr-mysql-data:/var/lib/mysql
secrets:
- mysql_root
healthcheck:
# --silent and redirecting stderr keeps healthcheck logs out of the main
# service log. The 10s start_period lets InnoDB recover before we gate on
# a successful ping.
test: ["CMD-SHELL", "mysqladmin ping --silent 2>/dev/null || exit 1"]
interval: 5s
timeout: 5s
retries: 20
start_period: 10s
# ClickHouse event archive (ADR-0015): the durable event store the server writes ingested events to and reads them back
# from. Reachable only on the private compose network (no host port), same posture as mysql. The default user is
# passwordless; the DSN rides a docker secret so a password can be added later without editing this file.
clickhouse:
image: clickhouse/clickhouse-server:24.8@sha256:1ffa82edee000a42c09313bd9f1293d94c570aee74babc1b3ca9983a35fa597b
restart: unless-stopped
environment:
CLICKHOUSE_DB: edr
# Required for the default user to authenticate over the network with an empty password; without it the server's
# ClickHouse ping fails with code 516 (AUTHENTICATION_FAILED). Mirrors the dev/demo clickhouse service.
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: "1"
ulimits:
# ClickHouse opens many files; the stock 1024 soft limit trips "too many open files" under load.
nofile:
soft: 262144
hard: 262144
volumes:
- edr-clickhouse-data:/var/lib/clickhouse
healthcheck:
test: ["CMD", "clickhouse-client", "--query", "SELECT 1"]
interval: 5s
timeout: 5s
retries: 20
start_period: 10s
server:
# Set EDR_VERSION in .env to pin a release tag (recommended). `latest` is
# fine for dev but unsafe for production because image digests can drift.
# For a local source build instead of a pull, layer the build override:
# docker compose -f docker-compose.prod.yml -f docker-compose.prod.build.yml up -d --build
image: ghcr.io/rawtrail/rawtrail-server:${EDR_VERSION:-latest}
restart: unless-stopped
# Longer than every stage of a graceful stop put together: the drain (EDR_SHUTDOWN_DRAIN,
# 30s), the in-flight deadline (15s), the two loop joins (10s + 5s) and the telemetry
# flush (5s): 65s in all. Docker's default is 10s, which cuts the drain the load
# balancer is watching and severs in-flight requests (#1127). test/arch keeps this
# in step with those five constants. Raise it too if you raise EDR_SHUTDOWN_DRAIN.
stop_grace_period: 90s
depends_on:
mysql:
condition: service_healthy
clickhouse:
condition: service_healthy
environment:
# The MySQL DSN needs the runtime root password that MYSQL reads from
# the same secret file. We consume it via *_FILE (see server/config/
# file_env.go) rather than interpolating so the password never lands in
# `docker inspect` output. The env key is blank here so the *_FILE path
# wins unconditionally; the server's fileBackedGetenv wrapper does the
# rest.
EDR_DSN: ""
EDR_DSN_FILE: /run/secrets/edr_dsn
EDR_ENROLL_SECRET_FILE: /run/secrets/enroll_secret
# Deployment root secret (>=32 bytes). Required unconditionally: the
# host-token HMAC pepper and other long-lived keys derive from it via HKDF
# (server/config/config.go loadSecretKey), so the server refuses to boot
# without it. Read from a docker-secret file so it never lands in
# `docker inspect`. Changing it invalidates every enrolled host.
EDR_SECRET_KEY_FILE: /run/secrets/secret_key
# ClickHouse event archive DSN (ADR-0015), the event store the server refuses to boot without. Passwordless on the
# private network; blank env so the *_FILE path wins and no value lands in `docker inspect`.
EDR_CLICKHOUSE_DSN: ""
EDR_CLICKHOUSE_DSN_FILE: /run/secrets/clickhouse_dsn
# TLS cert paths are required unless EDR_TLS_TERMINATED_BY_PROXY=1 says a
# proxy in front terminates TLS. Mount fullchain.pem + privkey.pem under
# ./tls/ (or override EDR_TLS_DIR to point at your cert store). The server
# refuses to boot when either path is empty or unreadable.
EDR_TLS_CERT_FILE: ${EDR_TLS_CERT_FILE:-/tls/fullchain.pem}
EDR_TLS_KEY_FILE: ${EDR_TLS_KEY_FILE:-/tls/privkey.pem}
EDR_LOG_LEVEL: ${EDR_LOG_LEVEL:-info}
EDR_LOG_FORMAT: "json"
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-}
OTEL_SERVICE_NAME: rawtrail-server
volumes:
# Optional: mount a tls dir if fullchain.pem + privkey.pem exist. The
# `:ro` flag + `tls:` default-empty env makes this safe when unused.
- ${EDR_TLS_DIR:-./tls}:/tls:ro
secrets:
- enroll_secret
- edr_dsn
- secret_key
- clickhouse_dsn
ports:
- "${EDR_LISTEN:-8088}:8088"
# No server-side HEALTHCHECK: the distroless/static base has no shell
# and no wget/curl, so `CMD-SHELL` healthchecks always fail. Nothing
# depends_on the server here, so operator-side readiness checks
# (curl http(s)://host:${EDR_LISTEN}/readyz) are the canonical path.
# If we ever need container-level health, compile a tiny static
# healthcheck binary into the image and invoke it via
# `HEALTHCHECK ["CMD", "/usr/local/bin/healthcheck"]` (no shell).
volumes:
edr-mysql-data:
edr-clickhouse-data:
secrets:
mysql_root:
file: ./secrets/mysql_root
enroll_secret:
file: ./secrets/enroll_secret
# edr_dsn is derived from mysql_root at `docker compose up` time via a
# compose-secret hack: the operator writes it once. See README.
edr_dsn:
file: ./secrets/edr_dsn
secret_key:
file: ./secrets/secret_key
# Fixed passwordless DSN pointing at the clickhouse service on the private
# network. In a secret file for parity with edr_dsn (a ClickHouse password,
# if added, would live here). See README.
clickhouse_dsn:
file: ./secrets/clickhouse_dsn