mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-25 07:00:48 +09:00
feat: add Docker Compose deployment support (#38)
- Add Docker Compose configuration for one-click deployment - Add Dockerfiles for server, agent, and web services - Add deployment script (deploy.sh) with automatic setup - Add comprehensive deployment documentation (DEPLOYMENT.md) - Use host Docker socket instead of DinD for better performance - Add Nginx configuration for web frontend - Add Makefile for common operations - Update README with Docker deployment quick start Features: - One-command deployment with ./deploy.sh - Automatic JWT secret generation - Health checks for all services - Data persistence with Docker volumes - Support for Bot container management via host Docker - Production-ready configuration examples Co-authored-by: root <root@DESKTOP-OU6H3GS.localdomain>
This commit is contained in:
@@ -0,0 +1,60 @@
|
|||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
*.md
|
||||||
|
docs/
|
||||||
|
assets/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.cursor/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
**/node_modules/
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
dist/
|
||||||
|
**/dist/
|
||||||
|
build/
|
||||||
|
**/build/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
*.tmp
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# Test
|
||||||
|
coverage/
|
||||||
|
.nyc_output/
|
||||||
|
|
||||||
|
# Mise
|
||||||
|
.mise.toml.local
|
||||||
|
|
||||||
|
# Data
|
||||||
|
data/
|
||||||
|
*.db
|
||||||
|
*.sqlite
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
docker-compose.override.yml
|
||||||
+401
@@ -0,0 +1,401 @@
|
|||||||
|
# Memoh Docker Deployment Guide
|
||||||
|
|
||||||
|
Deploy Memoh AI Agent System with Docker Compose in one command.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Clone the Repository
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/memohai/Memoh.git
|
||||||
|
cd Memoh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. One-Click Deployment
|
||||||
|
```bash
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The script will automatically:
|
||||||
|
- Check Docker and Docker Compose installation
|
||||||
|
- Create `.env` configuration file (if not exists)
|
||||||
|
- Generate random JWT secret
|
||||||
|
- Create `config.toml` configuration file
|
||||||
|
- Build MCP image
|
||||||
|
- Start all services
|
||||||
|
|
||||||
|
### 3. Access the Application
|
||||||
|
- Web UI: http://localhost
|
||||||
|
- API Service: http://localhost:8080
|
||||||
|
- Agent Gateway: http://localhost:8081
|
||||||
|
|
||||||
|
Default admin credentials:
|
||||||
|
- Username: `admin`
|
||||||
|
- Password: `admin123` (change in `.env`)
|
||||||
|
|
||||||
|
## Manual Deployment
|
||||||
|
|
||||||
|
If you prefer not to use the automated script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Create configuration files
|
||||||
|
cp .env.example .env
|
||||||
|
cp config.docker.toml config.toml
|
||||||
|
|
||||||
|
# 2. Edit configuration (Important!)
|
||||||
|
nano .env
|
||||||
|
|
||||||
|
# 3. Generate JWT secret
|
||||||
|
openssl rand -base64 32
|
||||||
|
|
||||||
|
# 4. Build MCP image
|
||||||
|
docker build -f cmd/mcp/Dockerfile -t memoh-mcp:latest .
|
||||||
|
|
||||||
|
# 5. Start services
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# 6. View logs
|
||||||
|
docker compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
This deployment uses the host's Docker daemon to manage Bot containers:
|
||||||
|
|
||||||
|
```
|
||||||
|
Host Docker
|
||||||
|
├── memoh-postgres (PostgreSQL)
|
||||||
|
├── memoh-qdrant (Qdrant)
|
||||||
|
├── memoh-server (Main Service) ← Manages Bot containers via /var/run/docker.sock
|
||||||
|
├── memoh-agent (Agent Gateway)
|
||||||
|
├── memoh-web (Web Frontend)
|
||||||
|
└── memoh-bot-* (Bot containers, dynamically created by main service)
|
||||||
|
```
|
||||||
|
|
||||||
|
Advantages:
|
||||||
|
- ✅ Lightweight, no additional Docker daemon needed
|
||||||
|
- ✅ Better performance, uses host container runtime directly
|
||||||
|
- ✅ Easier to manage and debug
|
||||||
|
- ✅ Lower resource consumption
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
### Using Make (Recommended)
|
||||||
|
```bash
|
||||||
|
make help # Show all commands
|
||||||
|
make deploy # One-click deployment
|
||||||
|
make logs # View logs
|
||||||
|
make restart # Restart services
|
||||||
|
make ps # View status
|
||||||
|
make backup # Backup data
|
||||||
|
make bots # View Bot containers
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Docker Compose
|
||||||
|
```bash
|
||||||
|
docker compose up -d # Start services
|
||||||
|
docker compose down # Stop services
|
||||||
|
docker compose logs -f # View logs
|
||||||
|
docker compose ps # View status
|
||||||
|
docker compose restart # Restart services
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Environment Variables (.env)
|
||||||
|
|
||||||
|
Key configuration items:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PostgreSQL password (must change)
|
||||||
|
POSTGRES_PASSWORD=your_secure_password
|
||||||
|
|
||||||
|
# JWT secret (must change)
|
||||||
|
JWT_SECRET=your_random_jwt_secret
|
||||||
|
|
||||||
|
# Admin account
|
||||||
|
ADMIN_USERNAME=admin
|
||||||
|
ADMIN_PASSWORD=your_admin_password
|
||||||
|
ADMIN_EMAIL=admin@yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Application Configuration (config.toml)
|
||||||
|
|
||||||
|
Main configuration items:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[postgres]
|
||||||
|
host = "postgres"
|
||||||
|
password = "your_secure_password" # Must match POSTGRES_PASSWORD in .env
|
||||||
|
|
||||||
|
[containerd]
|
||||||
|
socket_path = "unix:///var/run/docker.sock" # Use host Docker
|
||||||
|
|
||||||
|
[qdrant]
|
||||||
|
base_url = "http://qdrant:6334"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Service Overview
|
||||||
|
|
||||||
|
| Service | Container Name | Ports | Description |
|
||||||
|
|---------|---------------|-------|-------------|
|
||||||
|
| postgres | memoh-postgres | - | PostgreSQL database (internal only) |
|
||||||
|
| qdrant | memoh-qdrant | - | Qdrant vector database (internal only) |
|
||||||
|
| docker-cli | memoh-docker-cli | - | Docker CLI (uses host Docker) |
|
||||||
|
| server | memoh-server | 8080 | Main service (Go) |
|
||||||
|
| agent | memoh-agent | 8081 | Agent Gateway (Bun) |
|
||||||
|
| web | memoh-web | 80 | Web frontend (Nginx) |
|
||||||
|
|
||||||
|
## Data Persistence
|
||||||
|
|
||||||
|
Data is stored in Docker volumes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View volumes
|
||||||
|
docker volume ls | grep memoh
|
||||||
|
|
||||||
|
# Backup database
|
||||||
|
docker compose exec postgres pg_dump -U memoh memoh > backup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bot Container Management
|
||||||
|
|
||||||
|
Bot containers are dynamically created by the main service and run directly on the host:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View all Bot containers
|
||||||
|
make bots
|
||||||
|
# or
|
||||||
|
docker ps -a | grep memoh-bot
|
||||||
|
|
||||||
|
# View Bot logs
|
||||||
|
docker logs <bot-container-id>
|
||||||
|
|
||||||
|
# Enter Bot container
|
||||||
|
docker exec -it <bot-container-id> sh
|
||||||
|
|
||||||
|
# Stop Bot container
|
||||||
|
docker stop <bot-container-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backup and Restore
|
||||||
|
|
||||||
|
### Backup
|
||||||
|
```bash
|
||||||
|
# Create backup directory
|
||||||
|
mkdir -p backups
|
||||||
|
|
||||||
|
# Backup database
|
||||||
|
docker compose exec postgres pg_dump -U memoh memoh > backups/postgres_$(date +%Y%m%d).sql
|
||||||
|
|
||||||
|
# Backup Bot data
|
||||||
|
docker run --rm -v memoh_memoh_bot_data:/data -v $(pwd)/backups:/backup alpine \
|
||||||
|
tar czf /backup/bot_data_$(date +%Y%m%d).tar.gz -C /data .
|
||||||
|
|
||||||
|
# Backup configuration files
|
||||||
|
tar czf backups/config_$(date +%Y%m%d).tar.gz config.toml .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restore
|
||||||
|
```bash
|
||||||
|
# Restore database
|
||||||
|
docker compose exec -T postgres psql -U memoh memoh < backups/postgres_20240101.sql
|
||||||
|
|
||||||
|
# Restore Bot data
|
||||||
|
docker run --rm -v memoh_memoh_bot_data:/data -v $(pwd)/backups:/backup alpine \
|
||||||
|
tar xzf /backup/bot_data_20240101.tar.gz -C /data
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Services Won't Start
|
||||||
|
```bash
|
||||||
|
# View detailed logs
|
||||||
|
docker compose logs server
|
||||||
|
|
||||||
|
# Check configuration
|
||||||
|
docker compose config
|
||||||
|
|
||||||
|
# Rebuild
|
||||||
|
docker compose build --no-cache
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Connection Failed
|
||||||
|
```bash
|
||||||
|
# Check if database is ready
|
||||||
|
docker compose exec postgres pg_isready -U memoh
|
||||||
|
|
||||||
|
# Test connection
|
||||||
|
docker compose exec postgres psql -U memoh -d memoh
|
||||||
|
|
||||||
|
# View database logs
|
||||||
|
docker compose logs postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port Conflicts
|
||||||
|
```bash
|
||||||
|
# Check port usage
|
||||||
|
sudo netstat -tlnp | grep :8080
|
||||||
|
sudo netstat -tlnp | grep :80
|
||||||
|
|
||||||
|
# Modify port mapping in docker-compose.yml
|
||||||
|
# Example: change "80:80" to "8000:80"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Socket Permission Issues
|
||||||
|
```bash
|
||||||
|
# Add user to docker group
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
newgrp docker
|
||||||
|
|
||||||
|
# Check permissions
|
||||||
|
ls -la /var/run/docker.sock
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
### 1. Use HTTPS
|
||||||
|
|
||||||
|
Create `docker-compose.override.yml`:
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
ports:
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./ssl:/etc/nginx/ssl:ro
|
||||||
|
- ./nginx-https.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `nginx-https.conf`:
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name your-domain.com;
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name your-domain.com;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/cert.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/key.pem;
|
||||||
|
|
||||||
|
# SSL configuration
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
# Other configurations same as nginx.conf
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Resource Limits
|
||||||
|
|
||||||
|
Edit `docker-compose.yml` to add resource limits:
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '2'
|
||||||
|
memory: 2G
|
||||||
|
reservations:
|
||||||
|
cpus: '1'
|
||||||
|
memory: 1G
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Security Recommendations
|
||||||
|
|
||||||
|
Production environment recommendations:
|
||||||
|
- Use separate `.env` file
|
||||||
|
- Change all default passwords
|
||||||
|
- Use strong JWT secret
|
||||||
|
- Configure firewall rules
|
||||||
|
- Use HTTPS
|
||||||
|
- Regular data backups
|
||||||
|
- Limit containerd socket access permissions
|
||||||
|
- Run services as non-root user
|
||||||
|
- Configure log rotation
|
||||||
|
|
||||||
|
## Performance Optimization
|
||||||
|
|
||||||
|
### PostgreSQL Optimization
|
||||||
|
Create `postgres-custom.conf`:
|
||||||
|
```
|
||||||
|
shared_buffers = 2GB
|
||||||
|
effective_cache_size = 6GB
|
||||||
|
maintenance_work_mem = 512MB
|
||||||
|
checkpoint_completion_target = 0.9
|
||||||
|
wal_buffers = 16MB
|
||||||
|
```
|
||||||
|
|
||||||
|
Mount in `docker-compose.yml`:
|
||||||
|
```yaml
|
||||||
|
postgres:
|
||||||
|
volumes:
|
||||||
|
- ./postgres-custom.conf:/etc/postgresql/postgresql.conf:ro
|
||||||
|
command: postgres -c config_file=/etc/postgresql/postgresql.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Network Optimization
|
||||||
|
```yaml
|
||||||
|
networks:
|
||||||
|
memoh-network:
|
||||||
|
driver: bridge
|
||||||
|
driver_opts:
|
||||||
|
com.docker.network.driver.mtu: 1500
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update Application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull latest code
|
||||||
|
git pull
|
||||||
|
|
||||||
|
# Rebuild and restart
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
# Or use Make
|
||||||
|
make update
|
||||||
|
```
|
||||||
|
|
||||||
|
## Complete Uninstall
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop and remove all containers
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
# Remove data volumes (Warning! This deletes all data)
|
||||||
|
docker compose down -v
|
||||||
|
|
||||||
|
# Remove images
|
||||||
|
docker rmi memoh-mcp:latest
|
||||||
|
docker rmi $(docker images | grep memoh | awk '{print $3}')
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
⚠️ Important Security Notes:
|
||||||
|
|
||||||
|
1. **Docker Socket Access**: The main service container has access to the host Docker socket, which means the application can manage other containers on the host. Only run in trusted environments.
|
||||||
|
2. **Change Default Passwords**: Must change all default passwords in `.env`
|
||||||
|
3. **Strong JWT Secret**: Use a strong random JWT secret
|
||||||
|
4. **Firewall**: Configure firewall to only open necessary ports
|
||||||
|
5. **HTTPS**: Use HTTPS in production
|
||||||
|
6. **Regular Backups**: Regularly backup data
|
||||||
|
7. **Updates**: Regularly update images and dependencies
|
||||||
|
|
||||||
|
## Get Help
|
||||||
|
|
||||||
|
- Detailed Documentation: [DOCKER_DEPLOYMENT_CN.md](DOCKER_DEPLOYMENT_CN.md) (Chinese)
|
||||||
|
- GitHub Issues: https://github.com/memohai/Memoh/issues
|
||||||
|
- Telegram Group: https://t.me/memohai
|
||||||
|
- Email: business@memoh.net
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**That's it! Deploy Memoh in minutes!**
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
FROM oven/bun:1 AS builder
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
COPY agent/package.json agent/bun.lock* ./
|
||||||
|
|
||||||
|
RUN bun install
|
||||||
|
|
||||||
|
COPY agent/ ./
|
||||||
|
|
||||||
|
RUN bun run build
|
||||||
|
|
||||||
|
FROM oven/bun:1-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apk add --no-cache ca-certificates wget
|
||||||
|
|
||||||
|
COPY --from=builder /build/dist /app/dist
|
||||||
|
COPY --from=builder /build/node_modules /app/node_modules
|
||||||
|
COPY --from=builder /build/package.json /app/package.json
|
||||||
|
|
||||||
|
EXPOSE 8081
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8081/health || exit 1
|
||||||
|
|
||||||
|
CMD ["bun", "run", "dist/index.js"]
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
FROM golang:1.25-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
RUN apk add --no-cache git make
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||||
|
go build -trimpath -ldflags "-s -w" \
|
||||||
|
-o memoh-server ./cmd/agent/main.go
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apk add --no-cache ca-certificates tzdata wget
|
||||||
|
|
||||||
|
COPY --from=builder /build/memoh-server /app/memoh-server
|
||||||
|
|
||||||
|
COPY config.toml.example /app/config.toml.example
|
||||||
|
|
||||||
|
RUN mkdir -p /var/lib/memoh/data
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
||||||
|
|
||||||
|
CMD ["/app/memoh-server"]
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
FROM node:25-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
RUN npm install -g pnpm@10
|
||||||
|
|
||||||
|
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./
|
||||||
|
|
||||||
|
COPY packages ./packages
|
||||||
|
|
||||||
|
RUN pnpm install
|
||||||
|
|
||||||
|
ARG VITE_API_URL=http://localhost:8080
|
||||||
|
ARG VITE_AGENT_URL=http://localhost:8081
|
||||||
|
|
||||||
|
ENV VITE_API_URL=$VITE_API_URL
|
||||||
|
ENV VITE_AGENT_URL=$VITE_AGENT_URL
|
||||||
|
|
||||||
|
WORKDIR /build/packages/web
|
||||||
|
RUN pnpm build
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
COPY --from=builder /build/packages/web/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@@ -43,9 +43,23 @@ Memoh Bot can distinguish and remember requests from multiple humans and bots, w
|
|||||||
|
|
||||||
Please refer to the [Roadmap Version 0.1](https://github.com/memohai/Memoh/issues/2) for more details.
|
Please refer to the [Roadmap Version 0.1](https://github.com/memohai/Memoh/issues/2) for more details.
|
||||||
|
|
||||||
## Development
|
## Quick Start
|
||||||
|
|
||||||
Refer to [CONTRIBUTING.md](CONTRIBUTING.md) for more details.
|
### Docker Deployment (Recommended)
|
||||||
|
|
||||||
|
The fastest way to deploy Memoh:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/memohai/Memoh.git
|
||||||
|
cd Memoh
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Visit http://localhost after deployment. See [Docker Deployment Guide](README_DOCKER.md) for details.
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
Refer to [CONTRIBUTING.md](CONTRIBUTING.md) for development setup.
|
||||||
|
|
||||||
## Star History
|
## Star History
|
||||||
|
|
||||||
|
|||||||
+15
-1
@@ -43,7 +43,21 @@ Memoh Bot 能够区分并记忆来自多个人类/Bot 的请求,可在任意
|
|||||||
|
|
||||||
详情请参阅 [Roadmap Version 0.1](https://github.com/memohai/Memoh/issues/2)。
|
详情请参阅 [Roadmap Version 0.1](https://github.com/memohai/Memoh/issues/2)。
|
||||||
|
|
||||||
## 开发
|
## 快速开始
|
||||||
|
|
||||||
|
### Docker 部署(推荐)
|
||||||
|
|
||||||
|
最快的部署方式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/memohai/Memoh.git
|
||||||
|
cd Memoh
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
部署完成后访问 http://localhost。详见 [Docker 部署指南](README_DOCKER.md)。
|
||||||
|
|
||||||
|
### 开发环境
|
||||||
|
|
||||||
详见 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
详见 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
## Service configuration
|
||||||
|
[log]
|
||||||
|
level = "info"
|
||||||
|
format = "text"
|
||||||
|
|
||||||
|
[server]
|
||||||
|
addr = ":8080"
|
||||||
|
|
||||||
|
## Admin
|
||||||
|
[admin]
|
||||||
|
username = "admin"
|
||||||
|
password = "admin123"
|
||||||
|
email = "admin@memoh.local"
|
||||||
|
|
||||||
|
## Auth configuration
|
||||||
|
[auth]
|
||||||
|
jwt_secret = "YZq8kXrW5dFpNt9mLxQvHbRjKsMnOePw"
|
||||||
|
jwt_expires_in = "168h"
|
||||||
|
|
||||||
|
## Docker configuration (使用宿主机 Docker socket)
|
||||||
|
[containerd]
|
||||||
|
socket_path = "unix:///var/run/docker.sock"
|
||||||
|
namespace = "default"
|
||||||
|
|
||||||
|
[mcp]
|
||||||
|
busybox_image = "memoh-mcp:latest"
|
||||||
|
snapshotter = "overlayfs"
|
||||||
|
data_root = "/var/lib/memoh/data"
|
||||||
|
data_mount = "/data"
|
||||||
|
|
||||||
|
## Postgres configuration
|
||||||
|
[postgres]
|
||||||
|
host = "postgres"
|
||||||
|
port = 5432
|
||||||
|
user = "memoh"
|
||||||
|
password = "memoh123"
|
||||||
|
database = "memoh"
|
||||||
|
sslmode = "disable"
|
||||||
|
|
||||||
|
## Qdrant configuration
|
||||||
|
[qdrant]
|
||||||
|
base_url = "http://qdrant:6334"
|
||||||
|
api_key = ""
|
||||||
|
collection = "memory"
|
||||||
|
timeout_seconds = 10
|
||||||
|
|
||||||
|
## Agent Gateway
|
||||||
|
[agent_gateway]
|
||||||
|
host = "agent"
|
||||||
|
port = 8081
|
||||||
|
|
||||||
|
[brave]
|
||||||
|
api_key = ""
|
||||||
|
base_url = "https://api.search.brave.com/res/v1/"
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo -e "${GREEN}========================================${NC}"
|
||||||
|
echo -e "${GREEN} Memoh Docker Compose Deployment${NC}"
|
||||||
|
echo -e "${GREEN}========================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check Docker
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: Docker is not installed${NC}"
|
||||||
|
echo "Please install Docker first: https://docs.docker.com/get-docker/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check Docker Compose
|
||||||
|
if ! docker compose version &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: Docker Compose is not installed or version is too old${NC}"
|
||||||
|
echo "Please install Docker Compose v2.0+: https://docs.docker.com/compose/install/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓ Docker and Docker Compose are installed${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check .env file
|
||||||
|
if [ ! -f .env ]; then
|
||||||
|
echo -e "${YELLOW}⚠ .env file does not exist, creating...${NC}"
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# Generate random JWT secret
|
||||||
|
JWT_SECRET=$(openssl rand -base64 32 2>/dev/null || head -c 32 /dev/urandom | base64)
|
||||||
|
sed -i.bak "s|JWT_SECRET=.*|JWT_SECRET=$JWT_SECRET|g" .env
|
||||||
|
rm -f .env.bak
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓ .env file created${NC}"
|
||||||
|
echo -e "${YELLOW}⚠ Please edit .env file to change default passwords and configuration${NC}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check config.toml
|
||||||
|
if [ ! -f config.toml ]; then
|
||||||
|
echo -e "${YELLOW}⚠ config.toml does not exist, creating...${NC}"
|
||||||
|
cp config.docker.toml config.toml
|
||||||
|
echo -e "${GREEN}✓ config.toml created${NC}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build MCP image
|
||||||
|
echo -e "${GREEN}Building MCP image...${NC}"
|
||||||
|
if docker build -f cmd/mcp/Dockerfile -t memoh-mcp:latest . > /dev/null 2>&1; then
|
||||||
|
echo -e "${GREEN}✓ MCP image built successfully${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}⚠ MCP image build failed, will try to pull at runtime${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Start services
|
||||||
|
echo -e "${GREEN}Starting services...${NC}"
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}========================================${NC}"
|
||||||
|
echo -e "${GREEN} Deployment Complete!${NC}"
|
||||||
|
echo -e "${GREEN}========================================${NC}"
|
||||||
|
echo ""
|
||||||
|
echo "Service URLs:"
|
||||||
|
echo " - Web UI: http://localhost"
|
||||||
|
echo " - API Service: http://localhost:8080"
|
||||||
|
echo " - Agent Gateway: http://localhost:8081"
|
||||||
|
echo ""
|
||||||
|
echo "View service status:"
|
||||||
|
echo " docker compose ps"
|
||||||
|
echo ""
|
||||||
|
echo "View logs:"
|
||||||
|
echo " docker compose logs -f"
|
||||||
|
echo ""
|
||||||
|
echo "Stop services:"
|
||||||
|
echo " docker compose down"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}⚠ First startup may take 1-2 minutes, please be patient${NC}"
|
||||||
|
echo ""
|
||||||
|
echo "View detailed documentation: DEPLOYMENT.md"
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
services:
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: memoh-postgres
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: memoh
|
||||||
|
POSTGRES_USER: memoh
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-memoh123}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
- ./db/migrations:/docker-entrypoint-initdb.d:ro
|
||||||
|
expose:
|
||||||
|
- "5432"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U memoh"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- memoh-network
|
||||||
|
|
||||||
|
qdrant:
|
||||||
|
image: qdrant/qdrant:latest
|
||||||
|
container_name: memoh-qdrant
|
||||||
|
volumes:
|
||||||
|
- qdrant_data:/qdrant/storage
|
||||||
|
expose:
|
||||||
|
- "6333"
|
||||||
|
- "6334"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "timeout 10s bash -c ':> /dev/tcp/127.0.0.1/6333' || exit 1"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- memoh-network
|
||||||
|
|
||||||
|
docker-cli:
|
||||||
|
image: docker:27-cli
|
||||||
|
container_name: memoh-docker-cli
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- memoh_bot_data:/var/lib/memoh/data
|
||||||
|
command: ["tail", "-f", "/dev/null"]
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- memoh-network
|
||||||
|
|
||||||
|
server:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.server
|
||||||
|
container_name: memoh-server
|
||||||
|
environment:
|
||||||
|
- LOG_LEVEL=${LOG_LEVEL:-info}
|
||||||
|
- SERVER_ADDR=:8080
|
||||||
|
- POSTGRES_HOST=postgres
|
||||||
|
- POSTGRES_PORT=5432
|
||||||
|
- POSTGRES_USER=memoh
|
||||||
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-memoh123}
|
||||||
|
- POSTGRES_DB=memoh
|
||||||
|
- POSTGRES_SSLMODE=disable
|
||||||
|
- QDRANT_BASE_URL=http://qdrant:6334
|
||||||
|
- QDRANT_COLLECTION=memory
|
||||||
|
- CONTAINERD_SOCKET=unix:///var/run/docker.sock
|
||||||
|
- AGENT_GATEWAY_HOST=agent
|
||||||
|
- AGENT_GATEWAY_PORT=8081
|
||||||
|
- JWT_SECRET=${JWT_SECRET:-YZq8kXrW5dFpNt9mLxQvHbRjKsMnOePw}
|
||||||
|
- JWT_EXPIRES_IN=168h
|
||||||
|
- ADMIN_USERNAME=${ADMIN_USERNAME:-admin}
|
||||||
|
- ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin123}
|
||||||
|
- ADMIN_EMAIL=${ADMIN_EMAIL:-admin@memoh.local}
|
||||||
|
- MCP_BUSYBOX_IMAGE=memoh-mcp:latest
|
||||||
|
- MCP_DATA_ROOT=/var/lib/memoh/data
|
||||||
|
- MCP_DATA_MOUNT=/data
|
||||||
|
volumes:
|
||||||
|
- ./config.toml:/app/config.toml:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- memoh_bot_data:/var/lib/memoh/data
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
qdrant:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- memoh-network
|
||||||
|
|
||||||
|
agent:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.agent
|
||||||
|
container_name: memoh-agent
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- PORT=8081
|
||||||
|
ports:
|
||||||
|
- "8081:8081"
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- memoh-network
|
||||||
|
|
||||||
|
web:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.web
|
||||||
|
args:
|
||||||
|
- VITE_API_URL=${VITE_API_URL:-http://localhost:8080}
|
||||||
|
- VITE_AGENT_URL=${VITE_AGENT_URL:-http://localhost:8081}
|
||||||
|
container_name: memoh-web
|
||||||
|
ports:
|
||||||
|
- "8090:80"
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
- agent
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- memoh-network
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
driver: local
|
||||||
|
qdrant_data:
|
||||||
|
driver: local
|
||||||
|
memoh_bot_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
networks:
|
||||||
|
memoh-network:
|
||||||
|
driver: bridge
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Gzip 压缩
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
|
||||||
|
|
||||||
|
# 前端路由
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API 代理
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://memoh-server:8080/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# 超时设置
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Agent Gateway 代理
|
||||||
|
location /agent/ {
|
||||||
|
proxy_pass http://memoh-agent:8081/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# 超时设置
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 静态资源缓存
|
||||||
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 安全头
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user