Getting Started
Run MediaMoth Core with Docker Compose to expose the media, workflow, job, and search APIs on one gRPC endpoint. This setup pulls the versioned Core image and runs its required PostgreSQL, Kafka, Redis, and Elasticsearch services.
Prerequisites
- Docker with Docker Compose v2
- The hostname of a registry containing the MediaMoth release images
- Registry credentials, when the registry requires authentication
MediaMoth images use registry/service:vX.Y.Z names.
Configure the release
Create a directory for the deployment:
mkdir mediamoth
cd mediamothCreate an .env file and replace registry.example.com with the MediaMoth registry hostname:
MEDIAMOTH_REGISTRY=registry.example.com
MEDIAMOTH_CORE_VERSION=v1.0.0Authenticate before pulling when the registry is private:
docker login registry.example.comCreate the Compose file
Create compose.yaml with the following Core deployment:
services:
kafka:
image: confluentinc/cp-kafka:latest
restart: unless-stopped
environment:
KAFKA_NODE_ID: 1
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_NUM_PARTITIONS: 3
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk
healthcheck:
test:
- CMD
- bash
- -c
- kafka-broker-api-versions --bootstrap-server localhost:9092
interval: 10s
timeout: 5s
retries: 5
start_period: 40s
volumes:
- kafka_data:/var/lib/kafka/data
postgres-db:
image: postgres:18-alpine
restart: unless-stopped
environment:
POSTGRES_USER: mediamoth_core_user
POSTGRES_PASSWORD: mediamoth_core_pass
POSTGRES_DB: mediamoth_core
healthcheck:
test:
- CMD-SHELL
- pg_isready -U mediamoth_core_user -d mediamoth_core
interval: 10s
timeout: 5s
retries: 5
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --appendonly yes
healthcheck:
test: [CMD, redis-cli, ping]
interval: 10s
timeout: 5s
retries: 5
volumes:
- redis_data:/data
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.14.3
restart: unless-stopped
environment:
discovery.type: single-node
xpack.security.enabled: "false"
xpack.security.enrollment.enabled: "false"
ES_JAVA_OPTS: -Xms1g -Xmx1g
healthcheck:
test:
- CMD-SHELL
- curl -f http://localhost:9200/_cluster/health
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
mediamoth-core:
image: "${MEDIAMOTH_REGISTRY:?Set MEDIAMOTH_REGISTRY}/mediamoth-core:${MEDIAMOTH_CORE_VERSION:-v1.0.0}"
restart: unless-stopped
command: [serve]
depends_on:
kafka:
condition: service_healthy
postgres-db:
condition: service_healthy
redis:
condition: service_healthy
elasticsearch:
condition: service_healthy
ports:
- "127.0.0.1:50051:50051"
healthcheck:
test: [CMD, /grpc_health_probe, -addr=:50051]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
volumes:
kafka_data:
postgres_data:
redis_data:
elasticsearch_data:The Core image contains its runtime configuration. The Compose service names and database credentials above match that configuration. At startup, Core applies its migrations and creates the workflow, media, job, search, and event_store schemas.
WARNING
The example binds Core to the local host and uses first-run database credentials. Before exposing Core to another network, change POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB, then set the matching EVENT_STORE_DB__USERNAME, EVENT_STORE_DB__PASSWORD, and EVENT_STORE_DB__TABLE values on mediamoth-core.
Pull and start
Pull every image referenced by the deployment:
docker compose pullStart the stack in the background:
docker compose up -dThe first start waits for PostgreSQL, Kafka, Redis, and Elasticsearch to become healthy before starting Core.
Verify Core
Inspect container health:
docker compose psRun the gRPC health probe included in the Core image:
docker compose exec mediamoth-core /grpc_health_probe -addr=:50051A successful probe prints status: SERVING. If Core does not become healthy, inspect its startup and migration logs:
docker compose logs mediamoth-coreGenerated clients connect to localhost:50051 from the Docker host. Containers in the same Compose network connect to mediamoth-core:50051 for every Core API family.
This stack launches the orchestration APIs but does not include a media-processing worker or user interface. Add the workers needed by your pipelines after Core is healthy.
Operate the stack
Follow logs from every container:
docker compose logs -fStop the containers without deleting persistent data:
docker compose downThe named volumes retain Core data, Kafka data, Redis data, and search indexes. Running docker compose down --volumes deletes that state.
Develop from source
Clone the repository and install its pinned tools when contributing to MediaMoth:
git clone [email protected]:mediamoth/mediamoth.git
cd mediamoth
cp .mise.local.toml.example .mise.local.toml
mise trust
mise installSet GITHUB_TOKEN for private Go modules, then start the source-development stack:
export GOPRIVATE=github.com/mediamoth
export GITHUB_TOKEN="$(gh auth token)"
mise run dev:mediamoth-coreUse mise tasks to list worker, test, lint, and database tasks.