---
title: "Docker"
description: "Run Basic Memory in a container for server deployments, CI, and controlled self-hosted MCP experiments."
canonical_url: "https://docs.basicmemory.com/reference/docker"
---
# Docker

> Run Basic Memory in a container for server deployments, CI, and controlled self-hosted MCP experiments.

<warning>

Docker is an advanced deployment path. For most local desktop and coding tools, install Basic Memory with `uv tool install basic-memory` or Homebrew and let the tool launch `uvx basic-memory mcp`.

</warning>

## What Docker is for

The official Docker image runs the Basic Memory MCP server in a container. It is useful when you want:

- A repeatable server deployment
- Docker Compose or Kubernetes orchestration
- A shared test environment
- CI jobs that need Basic Memory available over HTTP
- A controlled self-hosted MCP experiment

It is **not** the recommended path for day-one local use. Local MCP clients usually expect a stdio process they can launch themselves. See [Local Install](https://docs.basicmemory.com/local/local-install) for that setup.

## Image

The image is published to GitHub Container Registry:

```bash
docker pull ghcr.io/basicmachines-co/basic-memory:latest
```

The image is built from the [Basic Memory repository](https://github.com/basicmachines-co/basic-memory) and runs as a non-root user.

## Run a container

Mount a local knowledge folder and expose the MCP server:

```bash
docker run -d \
  --name basic-memory-server \
  -p 8000:8000 \
  -v "$PWD/knowledge:/app/data" \
  -v basic-memory-config:/home/appuser/.basic-memory \
  ghcr.io/basicmachines-co/basic-memory:latest
```

The server listens on port `8000`.

<caution>

The container's SSE and HTTP endpoints are not secured by Basic Memory. Do not expose them directly to the public internet. Put authentication, TLS, and network access controls in front of any remote deployment.

</caution>

## Docker Compose

Use Compose when you want persistent configuration and a repeatable project mount:

```yaml
services:
  basic-memory:
    image: ghcr.io/basicmachines-co/basic-memory:latest
    container_name: basic-memory-server
    ports:
      - "8000:8000"
    volumes:
      - basic-memory-config:/home/appuser/.basic-memory:rw
      - ./knowledge:/app/data:rw
    environment:
      - BASIC_MEMORY_DEFAULT_PROJECT=main
      - BASIC_MEMORY_INDEX_CHANGES=true
      - BASIC_MEMORY_LOG_LEVEL=INFO
      - BASIC_MEMORY_INDEX_DELAY=1000
    command: ["basic-memory", "mcp", "--transport", "sse", "--host", "0.0.0.0", "--port", "8000"]
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "basic-memory", "--version"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

volumes:
  basic-memory-config:
```

Start it:

```bash
docker compose up -d
```

Check logs:

```bash
docker logs basic-memory-server
```

## Configuration

Configuration comes from these environment variables — the image itself sets `BASIC_MEMORY_HOME` and `BASIC_MEMORY_PROJECT_ROOT`; the rest are set by the Compose example (shown with their application defaults):

<table>
<thead>
  <tr>
    <th>
      Variable
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Purpose
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        BASIC_MEMORY_HOME
      </code>
    </td>
    
    <td>
      <code>
        /app/data/basic-memory
      </code>
    </td>
    
    <td>
      Basic Memory home inside the container
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        BASIC_MEMORY_PROJECT_ROOT
      </code>
    </td>
    
    <td>
      <code>
        /app/data
      </code>
    </td>
    
    <td>
      Root directory for mounted projects. Project names must be a single path segment (<code>
        research-2026
      </code>
      
      , not <code>
        Research/2026
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        BASIC_MEMORY_DEFAULT_PROJECT
      </code>
    </td>
    
    <td>
      <code>
        main
      </code>
      
       in the Compose example
    </td>
    
    <td>
      Default project name
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        BASIC_MEMORY_INDEX_CHANGES
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
      
       in the Compose example
    </td>
    
    <td>
      Enable real-time indexing of file changes
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        BASIC_MEMORY_LOG_LEVEL
      </code>
    </td>
    
    <td>
      <code>
        INFO
      </code>
      
       in the Compose example
    </td>
    
    <td>
      Log verbosity
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        BASIC_MEMORY_INDEX_DELAY
      </code>
    </td>
    
    <td>
      <code>
        1000
      </code>
      
       in the Compose example
    </td>
    
    <td>
      File-change indexing delay in milliseconds
    </td>
  </tr>
</tbody>
</table>

Mount two kinds of storage:

- **Knowledge files:** mount your Markdown/project directory at `/app/data`.
- **Configuration and local index:** mount `/home/appuser/.basic-memory` to a named volume so configuration and database state survive container restarts.

## Connect a client

The Docker image starts Basic Memory with SSE transport by default:

```bash
basic-memory mcp --transport sse --host 0.0.0.0 --port 8000
```

The image passes `--host 0.0.0.0` explicitly so the server is reachable through the container's port mapping. Since v0.24, `bm mcp` binds HTTP transports to `127.0.0.1` when `--host` is omitted. If you override the container command, keep `--host 0.0.0.0` or the published port will not answer. The server has no authentication, so publish the port only on a network you trust. For example, map it to the host's loopback with `-p 127.0.0.1:8000:8000`. To restrict which `Host` or `Origin` headers are accepted, set `FASTMCP_HTTP_ALLOWED_HOSTS` and `FASTMCP_HTTP_ALLOWED_ORIGINS`.

Use Docker only with clients or gateways that can reach an HTTP/SSE MCP server. If your client expects local stdio config, use the local install path instead:

```json
{
  "mcpServers": {
    "basic-memory": {
      "command": "uvx",
      "args": ["basic-memory", "mcp"]
    }
  }
}
```

## Run CLI commands inside the container

You can inspect the container with normal Basic Memory commands:

```bash
docker exec basic-memory-server basic-memory --version
docker exec basic-memory-server bm status
docker exec basic-memory-server bm project list
```

Use `docker exec` for diagnostics and scripted maintenance. For everyday local work, use the installed CLI on your host machine.

## PostgreSQL backend

Basic Memory supports **PostgreSQL with pgvector** as a database backend — it's the same configuration Basic Memory Cloud runs on. Point your container at a Postgres instance with two environment variables:

```bash
BASIC_MEMORY_DATABASE_BACKEND=postgres
BASIC_MEMORY_DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/dbname
```

Connection pooling is tuned via `db_pool_size`, `db_pool_overflow`, and `db_pool_recycle` — see [Configuration](https://docs.basicmemory.com/reference/configuration#database-settings). SQLite remains the default and needs no setup.

## Troubleshooting

### Port 8000 is already in use

Map a different host port:

```bash
docker run -d \
  -p 3000:8000 \
  -v "$PWD/knowledge:/app/data" \
  -v basic-memory-config:/home/appuser/.basic-memory \
  ghcr.io/basicmachines-co/basic-memory:latest
```

The container still listens on `8000`; the host listens on `3000`.

### Permission denied on mounted files

The container runs as a non-root user. If it cannot read or write your mounted directory, fix ownership or run with a matching user:

```bash
sudo chown -R 1000:1000 ./knowledge
```

or:

```bash
docker run --user "$(id -u):$(id -g)" ...
```

### The client cannot connect

Check three things:

1. The container is running: `docker ps`
2. The server logs are clean: `docker logs basic-memory-server`
3. Your client supports the transport you configured
4. A custom `command` still passes `--host 0.0.0.0` (the v0.24 default is `127.0.0.1`, which is unreachable from outside the container)

If the client only supports local stdio MCP, Docker is the wrong connection path. Use [Local MCP tools](https://docs.basicmemory.com/local/mcp-tools-local) instead.

## Build from source

Clone the Basic Memory source repository and build the image locally:

```bash
git clone https://github.com/basicmachines-co/basic-memory.git
cd basic-memory
docker build -t basic-memory:local .
```

You can pass custom UID/GID build arguments if your deployment needs specific file ownership:

```bash
docker build \
  --build-arg UID=1001 \
  --build-arg GID=1001 \
  -t basic-memory:custom .
```

## See also

<card-group>
<card icon="i-lucide-terminal" title="Local Install" to="https://docs.basicmemory.com/local/local-install">

Install Basic Memory for local desktop and coding tools.

</card>

<card icon="i-lucide-square-terminal" title="CLI Reference" to="https://docs.basicmemory.com/reference/cli-reference">

Look up Basic Memory commands and flags.

</card>

<card icon="i-lucide-life-buoy" title="Troubleshooting" to="https://docs.basicmemory.com/reference/troubleshooting">

Diagnose install, MCP, sync, and routing problems.

</card>
</card-group>


## Sitemap

See the full [sitemap](https://docs.basicmemory.com/sitemap.md) for all pages.
