# How to Deploy BettaFish Using Docker-Compose: Complete Setup Guide

> Deploy BettaFish quickly with Docker Compose. Follow our guide to set up the Flask UI and PostgreSQL database in minutes. Get started now!

- Repository: [BaiFu/bettafish](https://github.com/666ghj/bettafish)
- Tags: how-to-guide
- Published: 2026-02-23

---

**Deploy BettaFish in minutes by copying `.env.example` to `.env`, configuring your credentials, and running `docker compose up -d` to launch the Flask UI on port 5000 and PostgreSQL on port 5444.**

BettaFish is an open-source AI agent platform that combines Flask and Streamlit interfaces with a PostgreSQL backend. This guide walks you through the complete process to deploy BettaFish using docker-compose based on the official `666ghj/bettafish` repository structure.

## Docker-Compose Architecture Overview

The deployment consists of two services defined in [`docker-compose.yml`](https://github.com/666ghj/bettafish/blob/main/docker-compose.yml) at the repository root. This two-service stack isolates the application logic from data persistence, allowing each component to scale and restart independently.

### The BettaFish Application Service

The `bettafish` container runs the main Flask application and three Streamlit agents:

- **Image**: `ghcr.io/666ghj/bettafish:latest` (GitHub Container Registry)
- **Alternative Mirror**: `ghcr.nju.edu.cn/666ghj/bettafish:latest` (available for regions with slow GitHub connectivity)
- **Ports**: 
  - `5000:5000` for the Flask UI
  - `8501:8501` for the Insight agent
  - `8502:8502` for the Media agent  
  - `8503:8503` for the Query agent
- **Volumes**: Mounts for `./logs`, `./final_reports`, `./.env`, and engine-specific output directories (`insight_engine_streamlit_reports`, `media_engine_streamlit_reports`, `query_engine_streamlit_reports`)
- **Environment**: `PYTHONUNBUFFERED=1` ensures real-time logging; `STREAMLIT_SERVER_ENABLE_FILE_WATCHER=false` disables hot-reload to prevent Docker volume conflicts

### The PostgreSQL Database Service

The `db` container provides persistent storage for the Insight engine:

- **Image**: `postgres:15`
- **Port mapping**: `${POSTGRES_PORT:-5444}:5432` (defaults to host port 5444)
- **Credentials**: Reads `POSTGRES_USER`, `POSTGRES_PASSWORD`, and `POSTGRES_DB` from the `.env` file via the `env_file` directive
- **Persistent storage**: `./db_data:/var/lib/postgresql/data` preserves database files across container restarts
- **Networking**: The `bettafish` service connects using the hostname `db` as defined in the compose network

## Configuration Prerequisites

Before deploying, ensure you have Docker Engine 20.10+ and Docker Compose v2.0+ installed. The application requires a configured `.env` file located at the project root, which both services read at runtime according to the [`config.py`](https://github.com/666ghj/bettafish/blob/main/config.py) Pydantic settings class.

### Creating the Environment File

The repository includes `.env.example` as a configuration template. Create your production environment file by copying this template:

```bash
cp .env.example .env

```

Edit `.env` to configure the following required values:

- **Database settings**: Set `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_DB`, and optionally `POSTGRES_PORT` (default 5444)
- **LLM API keys**: Add your API keys for the Query, Media, and Insight agents as specified in the template
- **Application paths**: Ensure volume mount paths in [`docker-compose.yml`](https://github.com/666ghj/bettafish/blob/main/docker-compose.yml) match your host directory structure

## Step-by-Step Deployment Guide

Follow these commands to deploy BettaFish using docker-compose from the repository root:

1. **Clone the repository**

```bash
git clone https://github.com/666ghj/bettafish.git
cd bettafish

```

2. **Configure environment variables**

```bash
cp .env.example .env

# Edit .env with your database credentials and API keys

```

3. **Optional: Configure image mirror**

If you experience slow downloads from GitHub Container Registry, edit [`docker-compose.yml`](https://github.com/666ghj/bettafish/blob/main/docker-compose.yml) and switch to the commented mirror:

```yaml

# Comment out the default image

# image: ghcr.io/666ghj/bettafish:latest

# Uncomment the mirror

image: ghcr.nju.edu.cn/666ghj/bettafish:latest

```

4. **Launch the stack**

```bash
docker compose up -d

```

5. **Verify service status**

```bash
docker compose ps

```

Both containers should display status "Up". The `bettafish` service exposes the Flask UI on port 5000, while Streamlit agents run on ports 8501 (Insight), 8502 (Media), and 8503 (Query).

6. **Access the application**

- **Main Flask Interface**: http://localhost:5000
- **Insight Agent**: http://localhost:8501
- **Media Agent**: http://localhost:8502
- **Query Agent**: http://localhost:8503

## Troubleshooting Common Deployment Issues

If services fail to start or connections are refused, verify these common configuration problems:

**Connection refused on port 5000**

- **Cause**: The `bettafish` container is still initializing or has crashed due to a missing `.env` file
- **Fix**: Check logs with `docker compose logs bettafish` to identify startup errors. Ensure `.env` exists at the project root with valid `POSTGRES_USER` and `POSTGRES_PASSWORD` values

**Database authentication failures**

- **Cause**: Mismatch between credentials in `.env` and the initialized PostgreSQL data directory
- **Fix**: If you changed passwords after the first run, the existing data in `./db_data` conflicts with new credentials. Run `docker compose down -v` to remove the persistent volume, then `docker compose up -d` to reinitialize the database with current `.env` values

**Slow image pulls or timeout errors**

- **Cause**: Network latency to `ghcr.io` (GitHub Container Registry)
- **Fix**: Edit [`docker-compose.yml`](https://github.com/666ghj/bettafish/blob/main/docker-compose.yml) and uncomment the mirror image line `image: ghcr.nju.edu.cn/666ghj/bettafish:latest`. This uses the Nanjing University mirror for faster downloads in regions with slow GitHub connectivity

**Streamlit file watcher crashes**

- **Cause**: Streamlit's hot-reload feature conflicts with Docker volume mounts
- **Fix**: Verify that [`docker-compose.yml`](https://github.com/666ghj/bettafish/blob/main/docker-compose.yml) sets `STREAMLIT_SERVER_ENABLE_FILE_WATCHER=false` in the environment section. If you override this locally, ensure it remains disabled to prevent container crashes during file operations

## Summary

Deploying BettaFish using docker-compose requires only two configuration files and a single command:

- **Two-service architecture**: The `bettafish` container runs the Flask and Streamlit applications on ports 5000 and 8501-8503, while the `db` container provides PostgreSQL 15 persistence on port 5444
- **Centralized configuration**: Both services read database credentials and API keys from a single `.env` file mounted at the project root, as validated by [`config.py`](https://github.com/666ghj/bettafish/blob/main/config.py)
- **Persistent storage**: Volume mounts preserve logs, final reports, and database data in `./db_data` across container restarts
- **Quick start**: Run `cp .env.example .env`, configure your credentials, then `docker compose up -d` to access the complete AI agent platform

## Frequently Asked Questions

### How do I change the default database port when deploying BettaFish?

Set the `POSTGRES_PORT` variable in your `.env` file before starting the stack. The [`docker-compose.yml`](https://github.com/666ghj/bettafish/blob/main/docker-compose.yml) uses the syntax `${POSTGRES_PORT:-5444}`, which defaults to 5444 if unset. After changing this value, run `docker compose down` followed by `docker compose up -d` to apply the new port mapping to the host.

### Can I use a different PostgreSQL version than 15?

Yes, though the official [`docker-compose.yml`](https://github.com/666ghj/bettafish/blob/main/docker-compose.yml) specifies `postgres:15`. You can modify the image tag in the `db` service section to use `postgres:16` or `postgres:14`. Ensure you back up any existing data in `./db_data` before switching versions, as PostgreSQL major versions may require migration steps or data reinitialization.

### Why does the BettaFish container fail to start with database connection errors?

The application container attempts to connect to PostgreSQL immediately on startup. If the `db` container is still initializing or if the credentials in `.env` do not match the PostgreSQL environment variables, the connection will fail. Verify that `POSTGRES_USER`, `POSTGRES_PASSWORD`, and `POSTGRES_DB` are identical in both the application configuration and the database service definition. Use `docker compose logs db` to check PostgreSQL readiness and `docker compose logs bettafish` to view application connection attempts.

### Is it possible to deploy BettaFish without using docker-compose?

While docker-compose is the recommended deployment method for the `666ghj/bettafish` repository, you can run the containers manually using `docker run` commands or orchestrate them with Kubernetes. You would need to manually create the Docker network, start the PostgreSQL container with appropriate environment variables and volume mounts, then start the BettaFish container linked to that network with all required port mappings and volume configurations. The [`docker-compose.yml`](https://github.com/666ghj/bettafish/blob/main/docker-compose.yml) file serves as the authoritative reference for the required environment variables, port mappings, and volume paths needed for manual deployment.