# How to Deploy Thunderbolt Using Docker Compose: Complete Setup Guide

> Deploy Thunderbolt easily using Docker Compose. This guide details the multi-container setup orchestrated by docker-compose up --build for a seamless deployment experience.

- Repository: [Thunderbird/thunderbolt](https://github.com/thunderbird/thunderbolt)
- Tags: how-to-guide
- Published: 2026-04-19

---

**Thunderbolt deploys as a multi-container stack using the [`deploy/docker-compose.yml`](https://github.com/thunderbird/thunderbolt/blob/main/deploy/docker-compose.yml) file in the thunderbird/thunderbolt repository, which orchestrates React/Vite frontend, Bun backend, PostgreSQL, MongoDB, PowerSync, and Keycloak services with a single `docker compose up --build` command.**

Thunderbolt is a full-stack web application from the thunderbird organization that requires multiple services running in concert. Deploying Thunderbolt using Docker Compose provides a reproducible, containerized environment for local development or production testing without manual configuration of individual components.

## Architecture Overview

Thunderbolt consists of seven containerized services defined in [`deploy/docker-compose.yml`](https://github.com/thunderbird/thunderbolt/blob/main/deploy/docker-compose.yml). The frontend builds a static Vite bundle served via Nginx, while the backend runs a Node.js/Bun API server that handles database migrations on startup. Supporting infrastructure includes PostgreSQL for relational data, MongoDB replica sets for PowerSync document storage, the PowerSync real-time sync service, and an embedded Keycloak instance for OIDC authentication.

## Key Configuration Files

All deployment configurations reside in the `deploy/` directory at the repository root:

| File | Purpose |
|------|---------|
| [`deploy/docker-compose.yml`](https://github.com/thunderbird/thunderbolt/blob/main/deploy/docker-compose.yml) | Orchestrates all services and networking |
| `deploy/docker/frontend.Dockerfile` | Multi-stage build for React/Vite + Nginx |
| `deploy/docker/backend.Dockerfile` | Bun-based API server image |
| [`deploy/docker/backend-entrypoint.sh`](https://github.com/thunderbird/thunderbolt/blob/main/deploy/docker/backend-entrypoint.sh) | Entrypoint script that runs `bun drizzle-kit migrate` before starting the server |
| [`config/powersync-config.yaml`](https://github.com/thunderbird/thunderbolt/blob/main/config/powersync-config.yaml) | PowerSync sync rules and table configurations |
| [`config/keycloak-realm.json`](https://github.com/thunderbird/thunderbolt/blob/main/config/keycloak-realm.json) | Pre-configured Keycloak realm with clients and users |

## Step-by-Step Deployment Guide

### 1. Clone the Repository

```bash
git clone https://github.com/thunderbird/thunderbolt.git
cd thunderbolt

```

### 2. Configure Environment Variables

Create a `.env` file in the project root (or copy from `.env.example`). At minimum, define secrets required by the backend and Keycloak:

```bash

# Example .env

BETTER_AUTH_SECRET=your-secret-key
POSTGRES_PASSWORD=secure-postgres-password
KEYCLOAK_ADMIN_PASSWORD=admin-password

```

### 3. Launch the Stack

Run the full stack with image builds:

```bash
docker compose -f deploy/docker-compose.yml up --build -d

```

The `--build` flag compiles the frontend and backend images from their respective Dockerfiles. The `-d` flag detaches the containers.

### 4. Verify Health Checks

Wait 30-60 seconds for all services to initialize. Check logs to confirm successful startup:

```bash
docker compose -f deploy/docker-compose.yml logs -f

```

Look for "Server started" messages from the backend and "ready for connections" from PostgreSQL and MongoDB.

### 5. Access the Application

| Service | URL | Default Port |
|---------|-----|--------------|
| Frontend UI | `http://localhost:3000` | `${FRONTEND_PORT:-3000}` |
| Backend API | `http://localhost:8000/v1` | `${BACKEND_PORT:-8000}` |
| Keycloak Admin | `http://localhost:8180/admin` | `${KEYCLOAK_PORT:-8180}` (default login: `admin`/`admin`) |

### 6. Shut Down

To stop and remove all containers and volumes:

```bash
docker compose -f deploy/docker-compose.yml down -v

```

The `-v` flag deletes persistent data in `pg_data` and `mongo_data` volumes.

## Custom Integration Examples

When integrating Thunderbolt into an existing Docker Compose stack, reference pre-built images rather than building from source:

```yaml
version: "3.9"

services:
  thunderbolt:
    image: thunderbolt/backend:latest
    ports:
      - "8000:8000"
    env_file: .env
    environment:
      DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres
      POWERSYNC_URL: http://powersync:8080
    depends_on:
      - postgres
      - powersync

  postgres:
    image: postgres:18-alpine
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
    volumes:
      - pg_data:/var/lib/postgresql/data

  powersync:
    image: journeyapps/powersync-service:latest
    environment:
      POWERSYNC_CONFIG_PATH: /config/config.yaml
    volumes:
      - ./config/powersync-config.yaml:/config/config.yaml

volumes:
  pg_data:

```

## Managing Migrations and Updates

The backend automatically runs database migrations on startup via [`deploy/docker/backend-entrypoint.sh`](https://github.com/thunderbird/thunderbolt/blob/main/deploy/docker/backend-entrypoint.sh), which executes `bun drizzle-kit migrate`. To run migrations manually (for example, after pulling updates):

```bash
docker compose -f deploy/docker-compose.yml run --rm backend bun drizzle-kit migrate

```

For updates, pull the latest code, rebuild images, and restart:

```bash
git pull origin main
docker compose -f deploy/docker-compose.yml up --build -d

```

## Summary

- Thunderbolt deploys via the [`deploy/docker-compose.yml`](https://github.com/thunderbird/thunderbolt/blob/main/deploy/docker-compose.yml) file in the thunderbird/thunderbolt repository, which orchestrates seven containerized services.
- The stack includes a React/Vite frontend, Bun backend, PostgreSQL, MongoDB replica set, PowerSync, and Keycloak.
- Deploy by cloning the repo, creating a `.env` file, and running `docker compose -f deploy/docker-compose.yml up --build -d`.
- The backend entrypoint at [`deploy/docker/backend-entrypoint.sh`](https://github.com/thunderbird/thunderbolt/blob/main/deploy/docker/backend-entrypoint.sh) handles database migrations automatically using `bun drizzle-kit migrate`.
- Access the frontend on port 3000, backend API on port 8000, and Keycloak admin on port 8180 by default.

## Frequently Asked Questions

### What ports does Thunderbolt expose by default?

By default, the Docker Compose configuration exposes the frontend on port 3000, the backend API on port 8000, and Keycloak on port 8180. These can be customized by setting the `FRONTEND_PORT`, `BACKEND_PORT`, and `KEYCLOAK_PORT` environment variables in your `.env` file before launching the stack.

### How do I run database migrations manually?

While the [`deploy/docker/backend-entrypoint.sh`](https://github.com/thunderbird/thunderbolt/blob/main/deploy/docker/backend-entrypoint.sh) script automatically runs `bun drizzle-kit migrate` on container startup, you can execute migrations manually using `docker compose run`. This is useful for debugging or after updating the database schema: `docker compose -f deploy/docker-compose.yml run --rm backend bun drizzle-kit migrate`.

### Can I use an existing PostgreSQL instance instead of the container?

Yes. To use an external PostgreSQL database, remove the `postgres` service from your custom Compose file and set the `DATABASE_URL` environment variable to point to your existing instance (e.g., `postgresql://username:password@hostname:5432/database`). Ensure network connectivity between the Thunderbolt backend container and your external database host.

### How do I customize the PowerSync configuration?

PowerSync behavior is controlled by the [`config/powersync-config.yaml`](https://github.com/thunderbird/thunderbolt/blob/main/config/powersync-config.yaml) file mounted into the PowerSync container. Modify this file to define sync rules, table mappings, and filtering logic before deployment. The Docker Compose file mounts this configuration at [`/config/config.yaml`](https://github.com/thunderbird/thunderbolt/blob/main//config/config.yaml) inside the `powersync` service container, and the `POWERSYNC_CONFIG_PATH` environment variable points to this location.