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

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

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 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
git clone https://github.com/666ghj/bettafish.git
cd bettafish
  1. Configure environment variables
cp .env.example .env

# Edit .env with your database credentials and API keys
  1. Optional: Configure image mirror

If you experience slow downloads from GitHub Container Registry, edit docker-compose.yml and switch to the commented mirror:


# Comment out the default image

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

# Uncomment the mirror

image: ghcr.nju.edu.cn/666ghj/bettafish:latest
  1. Launch the stack
docker compose up -d
  1. Verify service status
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).

  1. Access the application

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 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 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
  • 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 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 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 file serves as the authoritative reference for the required environment variables, port mappings, and volume paths needed for manual deployment.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →