> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mixpeek.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Run Mixpeek locally in one container

> Build one Docker image and start it with one docker run. The API, Studio, Ray engine, MVS, MongoDB and Redis run on your machine with no cluster.

One Docker image runs the whole Mixpeek platform on your machine: the API, Studio, the Ray engine, MVS, MongoDB, Redis and an S3-compatible object store. Docker is the only prerequisite to run it.

<Warning>
  Mixpeek does not publish this image to a public registry. It bundles MongoDB Community Server (SSPL-1.0) and MinIO (AGPL-3.0). You build it from the Mixpeek repository, which needs repository access.
</Warning>

## Requirements

| Item          | Requirement                                                                                                                                              |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Docker        | Docker Desktop or Docker Engine, with `buildx`                                                                                                           |
| Docker memory | 16 GB                                                                                                                                                    |
| Free disk     | 25 GB. A first build leaves a 12.3 GB build cache next to an image of about 5 GB, and a 100-document run leaves up to 3.9 GB of Ray spill on the volume. |
| Build tools   | `git` and `rsync`. The build needs them. Running the image does not.                                                                                     |
| Architecture  | `linux/arm64` or `linux/amd64`, built for the machine you build on                                                                                       |
| Network       | The build needs it. The running container works with the network off in its default mode.                                                                |

## Set it up

<Steps>
  <Step title="Build the image">
    Clone the repository. Stage Studio into the build context, then build.

    ```bash theme={null}
    git clone https://github.com/mixpeek/mixpeek.git
    cd mixpeek
    bash server/scripts/stage-studio-src.sh
    docker buildx build -f server/Dockerfile.standalone \
      -t mixpeek/standalone:dev --load server
    ```

    The build targets your machine's architecture. Add `--platform linux/arm64` or `--platform linux/amd64` to choose one.

    A cold build on an 8-CPU arm64 Linux VM with no cached images took 13 minutes 4 seconds. Later builds reuse cached layers.
  </Step>

  <Step title="Start the container">
    Set Docker's memory to 16 GB first. In Docker Desktop, open Settings, then Resources.

    ```bash theme={null}
    docker run -d --name mixpeek --stop-timeout 60 \
      -p 8000:8000 -p 3000:3000 -p 8099:8099 \
      -v mixpeek-data:/data \
      mixpeek/standalone:dev
    ```

    | Port   | Serves                     |
    | ------ | -------------------------- |
    | `8000` | The API                    |
    | `3000` | Studio                     |
    | `8099` | Health for every component |

    The volume `mixpeek-data` holds all state. Publish only these three ports.

    `--stop-timeout 60` gives the stack time to shut down. MVS needs about 10.6 seconds to stop cleanly. Docker waits 10 seconds by default, then kills the container. With the flag, `docker stop` takes about 23 seconds and exits 0.
  </Step>

  <Step title="Wait until it is healthy">
    ```bash theme={null}
    until curl -s localhost:8099/health | grep -q '"status": "healthy"'; do sleep 5; done
    ```

    The endpoint reports `starting` while Ray builds its Serve applications. In a clean-host run, `/ready` answered after 44 seconds and the seed step finished after 48 seconds. A restart with data on the volume takes about a minute. Allow up to 10 minutes on a cold start.

    If the status becomes `degraded`, run `docker logs mixpeek` and look for the component named in `/health`.
  </Step>

  <Step title="Read your credentials">
    The container creates one organization on first start and writes its API key to the volume.

    ```bash theme={null}
    docker exec mixpeek /app/standalone/entrypoint.sh credentials
    ```

    The command prints five lines: `MIXPEEK_API_KEY`, `MIXPEEK_NAMESPACE_ID`, `MIXPEEK_ORG_NAME`, `MIXPEEK_ORG_ID` and `MIXPEEK_API_URL`. The key survives restarts.

    Export them into your shell:

    ```bash theme={null}
    eval "$(docker exec mixpeek /app/standalone/entrypoint.sh credentials | sed 's/^/export /')"
    ```
  </Step>

  <Step title="Call the API">
    List the buckets in your namespace. The response includes the starter bucket the container seeds.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -s -X POST http://localhost:8000/v1/buckets/list \
        -H "Authorization: Bearer $MIXPEEK_API_KEY" \
        -H "X-Namespace: $MIXPEEK_NAMESPACE_ID" \
        -H "Content-Type: application/json" \
        -d '{}'
      ```

      ```python Python theme={null}
      import os
      import requests

      resp = requests.post(
          "http://localhost:8000/v1/buckets/list",
          headers={
              "Authorization": f"Bearer {os.environ['MIXPEEK_API_KEY']}",
              "X-Namespace": os.environ["MIXPEEK_NAMESPACE_ID"],
          },
          json={},
      )
      for bucket in resp.json()["results"]:
          print(bucket["bucket_name"], bucket["bucket_id"])
      ```

      ```javascript JavaScript theme={null}
      const resp = await fetch("http://localhost:8000/v1/buckets/list", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.MIXPEEK_API_KEY}`,
          "X-Namespace": process.env.MIXPEEK_NAMESPACE_ID,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({}),
      });
      const { results } = await resp.json();
      for (const bucket of results) console.log(bucket.bucket_name, bucket.bucket_id);
      ```
    </CodeGroup>

    The SDKs take the local address as well: `Mixpeek(api_key=..., base_url="http://localhost:8000")` in Python and `new Mixpeek({ apiKey, baseUrl: "http://localhost:8000" })` in JavaScript.
  </Step>

  <Step title="Open Studio">
    Open `http://localhost:3000`. Studio needs no sign-in. A banner across the top says authentication is bypassed. Studio calls the API in this container with the seeded key.

    The seeded namespace `default` holds a starter bucket, a starter collection and a retriever named `search`.
  </Step>
</Steps>

## Check that everything works

Two test suites ship inside the image. Both run against the container itself.

```bash theme={null}
docker exec mixpeek /app/standalone/entrypoint.sh e2e -n 100
docker exec mixpeek /app/standalone/entrypoint.sh matrix
```

| Suite    | What it does                                                                                                                                                             |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `e2e`    | Creates its own organization, uploads `-n` documents, runs a batch through Ray, queries a retriever, clusters the documents, and deletes everything it made.             |
| `matrix` | Runs create, list, get, update, delete and execute against every primitive the API exposes. It deletes what it made in reverse order and checks each delete returns 404. |

The matrix prints one row per primitive and operation. A row is `PASS`, `FAIL`, or `VOID` when the container cannot exercise it. The command exits with status 1 on any `FAIL` that is not a documented known failure. The report is at `/data/logs/lifecycle-matrix/lifecycle-matrix.md` inside the container.

## Choose the default extractor

The seeded namespace uses `text_extractor`. It runs the MiniLM model (`all-MiniLM-L6-v2`, 384 dimensions), and the image carries the weights. This default needs no API key and makes no paid call. It works with the network off.

To use the multimodal `universal_extractor` instead, pass a Gemini or OpenAI key and name the extractor. The container applies the default when it creates the organization, so start from an empty volume with `docker rm -f mixpeek && docker volume rm mixpeek-data`.

```bash theme={null}
docker run -d --name mixpeek --stop-timeout 60 \
  -p 8000:8000 -p 3000:3000 -p 8099:8099 \
  -v mixpeek-data:/data \
  -e GEMINI_API_KEY=... \
  -e GEMINI_PROJECT_ID=... \
  -e MIXPEEK_DEFAULT_NAMESPACE_EXTRACTOR=universal_extractor \
  mixpeek/standalone:dev
```

Calls to Gemini or OpenAI bill your provider account for each object processed. `/health` reports `"mode": "keyed"` when a key is present.

## Media extractors

The image serves two inference apps: MiniLM and `taxonomy_join`. It carries no GPU models. The image, audio and video extractors resolve to models such as SigLIP, CLAP or ArcFace, and the image does not include them.

The image accepts media files, detects their type, stores them and lists them. Only the embedding step cannot run. The media test driver reports that step as `VOID` and names the missing model:

```bash theme={null}
docker exec mixpeek python3 /app/standalone/media_lifecycle_e2e.py
```

In keyed mode, `universal_extractor` embeds media through the Gemini API.

## Add an extractor with YAML

Put a `*.yaml` file in a directory, mount it at `/data/plugins`, and restart the container. The extractor appears in the API next to the built-in ones. You write no Python and rebuild nothing.

```yaml theme={null}
name: product_copy_embedder
version: v1
description: Embeds product marketing copy with MiniLM.
extends: text_extractor/v1
input:
  field: content
output:
  vector_index:
    model: all_minilm_l6_v2_v1
```

```bash theme={null}
docker run -d --name mixpeek --stop-timeout 60 \
  -p 8000:8000 -p 3000:3000 -p 8099:8099 \
  -v mixpeek-data:/data \
  -v "$PWD/my-plugins":/data/plugins \
  mixpeek/standalone:dev
```

`extends` reuses a built-in extractor's definition and Ray pipeline. The model registry sets the vector dimensions, so the YAML does not state them. A spec that fails to load stops the container.

## Operate the container

| Task                   | Command                                                                             |
| ---------------------- | ----------------------------------------------------------------------------------- |
| Component health       | `curl -s localhost:8099/health`                                                     |
| Can it serve a request | `curl -s localhost:8099/ready`                                                      |
| Process table          | `docker exec mixpeek /app/standalone/entrypoint.sh status`                          |
| Task runtime           | `docker exec mixpeek /app/standalone/entrypoint.sh work`                            |
| Logs                   | `docker logs mixpeek`                                                               |
| Stop and start         | `docker stop mixpeek` then `docker start mixpeek`. The stop takes about 23 seconds. |
| Start over             | `docker rm -f mixpeek && docker volume rm mixpeek-data`                             |

The volume survives `docker stop`, `docker start` and replacing the container. If you delete the volume, the container creates a new organization and a new API key on the next start.

The image runs no Celery process and no broker. A Mongo-backed work ledger and a Ray dispatcher run the background tasks. `celery-worker` and `celery-beat` show as `disabled` in `/health`.

## Memory

Give Docker 16 GB. The idle container uses about 7.8 GiB, and 7.4 GiB of that is Ray.

| Docker memory | Measured result                                              |
| ------------- | ------------------------------------------------------------ |
| 6 GB          | The platform boots. Ray's memory monitor then kills workers. |
| 12 GB         | The platform boots. A 100-document batch does not finish.    |
| 16 GB         | The `e2e` and `matrix` suites complete.                      |

## What the image leaves out

| Left out   | What you see                                                                                                                              |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| ClickHouse | Analytics is off. The `/v1/analytics` endpoints answer empty. Events on your resources still land in the namespace `_signals` collection. |
| GPU models | E5-large, SigLIP, CLAP, DINOv2, the BGE reranker and ArcFace are absent.                                                                  |

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/docs/overview/quickstart">
    Create a namespace, add data and search.
  </Card>

  <Card title="Concepts" icon="book" href="/docs/overview/concepts">
    Namespaces, buckets, collections and retrievers.
  </Card>

  <Card title="Studio" icon="layer-group" href="/docs/studio/quickstart">
    Work with the same platform in the UI.
  </Card>

  <Card title="Deployment" icon="server" href="/docs/operations/deployment">
    Kubernetes and managed Ray topologies.
  </Card>
</CardGroup>
