Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.git
.github
node_modules/
frontend/node_modules/
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
env/
venv/
.venv/
.env
.openspace/
frontend/dist/
showcase/
gdpval_bench/
assets/
50 changes: 50 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# OpenSpace Docker Environment Configuration
# Copy this file to .env and customize your settings

# ==================== Required ====================
# Generate a secure random key for your OpenSpace instance
# You can generate one with: openssl rand -base64 32
OPENSPACE_API_KEY=your_openpspace_api_key_here

# ==================== LLM Providers ====================
# Choose ONE provider configuration below

# Option 1: OpenAI (GPT-4, GPT-3.5, etc.)
# OPENAI_API_KEY=sk-...

# Option 2: Anthropic (Claude)
# ANTHROPIC_API_KEY=sk-ant-...

# Option 3: StepFun (Step models via OpenRouter)
# Note: Using OpenRouter as the API gateway
OPENSPACE_MODEL=stepfun/step-3.5-flash:free
OPENSPACE_LLM_API_KEY=sk-or-v1-...
OPENSPACE_LLM_API_BASE=https://openrouter.ai/api/v1

# Option 4: Custom provider (Local LLM, Together, etc.)
# OPENSPACE_LLM_API_KEY=your_api_key
# OPENSPACE_LLM_API_BASE=https://your-llm-provider.com/v1
# OPENSPACE_MODEL=your-model-name

# ==================== Optional ====================
# Default model to use when not specified in queries
# OPENSPACE_MODEL=claude-3-7-sonnet-latest

# Enable debug logging (set to 1)
# OPENSPACE_DEBUG=0

# ==================== Docker Compose Configuration ====================
# Override default host port (default: 9001)
# HOST_PORT=9001

# Volume type: "named" (Docker-managed) or "bind" (host directory)
# VOLUME_TYPE=named

# When VOLUME_TYPE=named, these named volumes are used:
# VOLUME_DATA=openspace-data
# VOLUME_SKILLS=openspace-skills

# When VOLUME_TYPE=bind, create local directories:
# (not set via env, edit docker-compose.yml directly)
# - ./data:/app/.openspace
# - ./skills:/app/skills
283 changes: 283 additions & 0 deletions DOCKER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
# Docker Deployment for OpenSpace

This guide provides instructions on how to run OpenSpace in a Docker container. Containerization ensures a consistent environment, making it easy to run the dashboard and backend API without dealing with local Python and Node.js dependencies.

## Prerequisites

- [Docker](https://docs.docker.com/get-docker/) (20.10+)
- [Docker Compose](https://docs.docker.com/compose/install/) (v2.0+)

## Quick Start (Docker Compose)

The easiest way to get OpenSpace running is using `docker-compose`.

### 1. Clone the Repository

```bash
git clone https://github.com/HKUDS/OpenSpace.git
cd OpenSpace
git checkout feat/docker-deployment
```

### 2. Configure Environment Variables

```bash
# Copy the example environment file
cp .env.example .env

# Edit .env with your configuration
# Required at minimum:
# OPENSPACE_API_KEY=$(openssl rand -base64 32)
#
# Choose and configure ONE LLM provider:
# - OpenAI + OPENAI_API_KEY
# - Anthropic + ANTHROPIC_API_KEY
# - OpenRouter + OPENSPACE_LLM_API_KEY + OPENSPACE_LLM_API_BASE + OPENSPACE_MODEL
```

**Environment Variables Reference:**

| Variable | Required | Description |
|----------|----------|-------------|
| `OPENSPACE_API_KEY` | **Yes** | Secret API key for this OpenSpace instance. Generate with `openssl rand -base64 32` |
| `OPENAI_API_KEY` | No | OpenAI API key (sk-...) |
| `ANTHROPIC_API_KEY` | No | Anthropic API key (sk-ant-...) |
| `OPENSPACE_MODEL` | No | Default model name (e.g., `claude-3-7-sonnet-latest`, `stepfun/step-3.5-flash:free`) |
| `OPENSPACE_LLM_API_KEY` | No | API key for custom LLM provider |
| `OPENSPACE_LLM_API_BASE` | No | Base URL for custom LLM provider (e.g., `https://openrouter.ai/api/v1`) |
| `OPENSPACE_DEBUG` | No | Set to `1` to enable debug logging |
| `HOST_PORT` | No | Host port to expose (default: `9001`) |
| `VOLUME_TYPE` | No | `named` (default) or `bind` for local directories |

### 3. Build and Run

```bash
# Standard docker-compose (uses docker-compose.yml)
docker compose up -d --build

# For production with stricter resource limits:
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build

# To stop:
docker compose down

# To view logs:
docker compose logs -f openspace

# To check health status:
docker compose ps
```

### 4. Access the Dashboard

Open your browser and navigate to:

- **Dashboard:** http://localhost:${HOST_PORT:-9001}
- Health endpoint: http://localhost:${HOST_PORT:-9001}/health

The frontend and backend are served seamlessly from the same container.

---

## CLI Usage

You can use the container to execute OpenSpace CLI commands.

### Run a Query

```bash
docker exec -it openspace openspace --model "anthropic/claude-sonnet-4.5" --query "Analyze the local skills"
```

### Download/Upload Skills

```bash
docker exec -it openspace openspace-download-skill <skill_id>
docker exec -it openspace openspace-upload-skill /app/skills/my-skill
```

### Enter Container Shell

```bash
docker exec -it openspace bash
```

---

## Volume & Data Management

### Volume Types

1. **Named volumes** (default) - Managed by Docker, good for simple deployments
- `openspace-data`: Contains SQLite database (`openspace.db`) and skill history
- `openspace-skills`: Persists downloaded and custom skills

2. **Bind mounts** - Direct host directory access, better for development
Edit `docker-compose.yml`:
```yaml
volumes:
- ./data:/app/.openspace
- ./skills:/app/skills
```

### Backup & Restore

**Backup:**
```bash
# Named volumes
docker run --rm -v openspace-data:/data -v $(pwd):/backup alpine tar czf /backup/openspace-data-$(date +%Y%m%d).tar.gz -C /data .

# Bind mounts (just copy the directories)
cp -r data skills backup/
```

**Restore:**
```bash
# Named volumes
docker run --rm -v openspace-data:/data -v $(pwd):/backup alpine sh -c "rm -rf /data/* && tar xzf /backup/openspace-data-YYYYMMDD.tar.gz -C /data"

# Bind mounts
cp -r backup/data backup/skills ./
```

---

## Monitoring

### Health Check

OpenSpace container includes a health check that pings `/health` endpoint every 30 seconds. Check status:

```bash
docker compose ps
# Look for "healthy" in the STATUS column
```

### Prometheus Metrics

If you have a Prometheus instance, you can scrape metrics from OpenSpace. Add to your `docker-compose.yml`:

```yaml
services:
openspace:
# Add this label for service discovery
labels:
- "prometheus-job=openspace"
```

Then configure Prometheus to scrape `openspace:7788/metrics` (if endpoint is available).

### Logs

Logs are configured with rotation (10MB max, 3 files by default). View logs:

```bash
docker compose logs -f openspace
# Or with timestamps
docker compose logs -f --timestamp openspace
```

For centralized logging, consider using Loki/Promtail stack (not included by default).

---

## Troubleshooting

### Container fails to start

Check logs:
```bash
docker compose logs openspace
```

Common issues:
- **Missing OPENSPACE_API_KEY**: Set it in `.env` file
- **Port already in use**: Change `HOST_PORT` in `.env` or stop the conflicting service
- **Insufficient memory**: Increase Docker memory limit (Settings → Resources)

### Health check failing

The health check endpoint `/health` might not be available in older versions. If using a development build, you may need to disable the health check by removing it from `docker-compose.yml`.

### Permission denied on volumes

If using bind mounts, ensure the host directories are readable/writable by the container user (UID 1000). Fix with:
```bash
sudo chown -R 1000:1000 data skills
```

---

## Production Deployment Checklist

- [ ] Generate a strong `OPENSPACE_API_KEY` and keep it secret
- [ ] Configure SSL/TLS termination (use reverse proxy like nginx or Traefik)
- [ ] Set appropriate resource limits (memory: 2-4G, CPU: 2-4 cores)
- [ ] Enable log rotation and set up log aggregation
- [ ] Configure regular backups of `openspace-data` volume
- [ ] Set up monitoring (Prometheus + Grafana)
- [ ] Use `docker-compose.prod.yml` for additional production settings
- [ ] Restrict access to the API and dashboard via firewall/VPC
- [ ] Keep Docker and base images updated regularly

---

## Advanced Configuration

### Custom Network

To integrate with other services on a custom network:

```yaml
networks:
app-network:
driver: bridge

services:
openspace:
networks:
- app-network
```

### Multi-stage Deployment (with separate frontend/backend)

For large-scale deployments, you might split frontend and backend services. See `docker-compose.multi.yml` (if available).

### Environment-Specific Configs

Use multiple compose files:

```bash
# Development (with hot-reload, less resource limits)
docker compose -f docker-compose.yml -f docker-compose.override.yml up -d

# Production (strict limits, optimized)
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```

---

## Security Notes

- The Dockerfile creates and uses a non-root user `appuser` (UID 1000)
- `OPENSPACE_API_KEY` should be treated as a secret; rotate periodically
- Network access is limited to what the container needs; avoid `--network host`
- Keep the host and Docker daemon updated to prevent vulnerabilities

---

## Contributing

Found an issue or want to improve the Docker deployment? PRs welcome!

Please update:
- `docker-compose.yml` (core config)
- `Dockerfile` (build instructions)
- `DOCKER.md` (this documentation)
- Add/maintain `.env.example`

---

## License

MIT
Loading