Skip to content

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:

bash
mkdir mediamoth
cd mediamoth

Create an .env file and replace registry.example.com with the MediaMoth registry hostname:

dotenv
MEDIAMOTH_REGISTRY=registry.example.com
MEDIAMOTH_CORE_VERSION=v1.0.0

Authenticate before pulling when the registry is private:

bash
docker login registry.example.com

Create the Compose file

Create compose.yaml with the following Core deployment:

yaml
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:

bash
docker compose pull

Start the stack in the background:

bash
docker compose up -d

The first start waits for PostgreSQL, Kafka, Redis, and Elasticsearch to become healthy before starting Core.

Verify Core

Inspect container health:

bash
docker compose ps

Run the gRPC health probe included in the Core image:

bash
docker compose exec mediamoth-core /grpc_health_probe -addr=:50051

A successful probe prints status: SERVING. If Core does not become healthy, inspect its startup and migration logs:

bash
docker compose logs mediamoth-core

Generated 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:

bash
docker compose logs -f

Stop the containers without deleting persistent data:

bash
docker compose down

The 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:

bash
git clone [email protected]:mediamoth/mediamoth.git
cd mediamoth
cp .mise.local.toml.example .mise.local.toml
mise trust
mise install

Set GITHUB_TOKEN for private Go modules, then start the source-development stack:

bash
export GOPRIVATE=github.com/mediamoth
export GITHUB_TOKEN="$(gh auth token)"
mise run dev:mediamoth-core

Use mise tasks to list worker, test, lint, and database tasks.

Next steps

Released under the MIT License.