Skip to content

Docker 安装

使用 Docker 是部署 AnythingLLM 最简单、最可靠的方式。本指南将详细介绍如何使用 Docker 和 Docker Compose 安装和配置 AnythingLLM。

前置要求

系统要求

  • 操作系统: Linux, macOS, Windows (支持 Docker)
  • 内存: 最少 4GB RAM,推荐 8GB+
  • 存储: 最少 10GB 可用空间
  • CPU: 2 核心以上

软件要求

  • Docker: 版本 20.10 或更高
  • Docker Compose: 版本 2.0 或更高

安装 Docker

Linux (Ubuntu/Debian)

bash
# 更新包索引
sudo apt-get update

# 安装必要的包
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# 添加 Docker 官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 设置仓库
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 启动 Docker 服务
sudo systemctl start docker
sudo systemctl enable docker

# 将用户添加到 docker 组
sudo usermod -aG docker $USER

macOS

bash
# 使用 Homebrew 安装
brew install --cask docker

# 或者下载 Docker Desktop
# https://www.docker.com/products/docker-desktop/

Windows

powershell
# 下载并安装 Docker Desktop
# https://www.docker.com/products/docker-desktop/

# 或使用 Chocolatey
choco install docker-desktop

快速开始

单容器部署

bash
# 拉取最新镜像
docker pull mintplexlabs/anythingllm:latest

# 运行容器
docker run -d \
  --name anythingllm \
  -p 3001:3001 \
  -v anythingllm_storage:/app/storage \
  -e JWT_SECRET="your-super-secret-jwt-key" \
  -e OPENAI_API_KEY="your-openai-api-key" \
  mintplexlabs/anythingllm:latest

# 查看日志
docker logs -f anythingllm

使用环境文件

bash
# 创建环境文件
cat > .env << EOF
# 基础配置
NODE_ENV=production
SERVER_PORT=3001
JWT_SECRET=your-super-secret-jwt-key-change-this

# AI 模型配置
OPENAI_API_KEY=your-openai-api-key
OPENAI_MODEL=gpt-4

# 数据库配置
DATABASE_TYPE=sqlite
SQLITE_DB_PATH=/app/storage/anythingllm.db

# 向量数据库配置
CHROMA_ENDPOINT=http://chroma:8000
CHROMA_COLLECTION=anythingllm

# 存储配置
STORAGE_DIR=/app/storage
EOF

# 运行容器
docker run -d \
  --name anythingllm \
  -p 3001:3001 \
  -v anythingllm_storage:/app/storage \
  --env-file .env \
  mintplexlabs/anythingllm:latest

Docker Compose 部署

基础配置

yaml
# docker-compose.yml
version: '3.8'

services:
  anythingllm:
    image: mintplexlabs/anythingllm:latest
    container_name: anythingllm
    ports:
      - "3001:3001"
    volumes:
      - anythingllm_storage:/app/storage
      - ./logs:/app/logs
    environment:
      - NODE_ENV=production
      - SERVER_PORT=3001
      - JWT_SECRET=your-super-secret-jwt-key
      - OPENAI_API_KEY=your-openai-api-key
      - DATABASE_TYPE=sqlite
      - SQLITE_DB_PATH=/app/storage/anythingllm.db
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

volumes:
  anythingllm_storage:
    driver: local

完整配置(包含数据库和向量数据库)

yaml
# docker-compose.full.yml
version: '3.8'

services:
  # AnythingLLM 主应用
  anythingllm:
    image: mintplexlabs/anythingllm:latest
    container_name: anythingllm
    ports:
      - "3001:3001"
    volumes:
      - anythingllm_storage:/app/storage
      - ./logs:/app/logs
      - ./config:/app/config
    environment:
      - NODE_ENV=production
      - SERVER_PORT=3001
      - JWT_SECRET=your-super-secret-jwt-key
      
      # 数据库配置
      - DATABASE_TYPE=postgres
      - DB_HOST=postgres
      - DB_PORT=5432
      - DB_USERNAME=anythingllm
      - DB_PASSWORD=anythingllm_password
      - DB_NAME=anythingllm
      
      # AI 模型配置
      - OPENAI_API_KEY=your-openai-api-key
      - OPENAI_MODEL=gpt-4
      
      # 向量数据库配置
      - CHROMA_ENDPOINT=http://chroma:8000
      - CHROMA_COLLECTION=anythingllm
      
      # Redis 配置
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_PASSWORD=redis_password
    depends_on:
      postgres:
        condition: service_healthy
      chroma:
        condition: service_started
      redis:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  # PostgreSQL 数据库
  postgres:
    image: postgres:15-alpine
    container_name: anythingllm_postgres
    environment:
      - POSTGRES_DB=anythingllm
      - POSTGRES_USER=anythingllm
      - POSTGRES_PASSWORD=anythingllm_password
      - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d
    ports:
      - "5432:5432"
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U anythingllm -d anythingllm"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Chroma 向量数据库
  chroma:
    image: ghcr.io/chroma-core/chroma:latest
    container_name: anythingllm_chroma
    ports:
      - "8000:8000"
    volumes:
      - chroma_data:/chroma/chroma
    environment:
      - CHROMA_SERVER_HOST=0.0.0.0
      - CHROMA_SERVER_HTTP_PORT=8000
      - CHROMA_SERVER_CORS_ALLOW_ORIGINS=["*"]
    command: ["uvicorn", "chromadb.app:app", "--host", "0.0.0.0", "--port", "8000"]
    restart: unless-stopped

  # Redis 缓存
  redis:
    image: redis:7-alpine
    container_name: anythingllm_redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    command: redis-server --requirepass redis_password --appendonly yes
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

  # Nginx 反向代理
  nginx:
    image: nginx:alpine
    container_name: anythingllm_nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/ssl:/etc/nginx/ssl
      - ./nginx/logs:/var/log/nginx
    depends_on:
      - anythingllm
    restart: unless-stopped

volumes:
  anythingllm_storage:
    driver: local
  postgres_data:
    driver: local
  chroma_data:
    driver: local
  redis_data:
    driver: local

networks:
  default:
    name: anythingllm_network

启动服务

bash
# 使用基础配置启动
docker-compose up -d

# 使用完整配置启动
docker-compose -f docker-compose.full.yml up -d

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs -f anythingllm

# 停止服务
docker-compose down

# 停止并删除数据卷
docker-compose down -v

高级配置

环境变量文件

bash
# .env.production
# 基础配置
NODE_ENV=production
SERVER_PORT=3001
SERVER_HOST=0.0.0.0
APP_URL=https://anythingllm.yourdomain.com

# 安全配置
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
FORCE_HTTPS=true
CORS_ORIGINS=https://yourdomain.com

# 数据库配置
DATABASE_TYPE=postgres
DB_HOST=postgres
DB_PORT=5432
DB_USERNAME=anythingllm
DB_PASSWORD=your-secure-database-password
DB_NAME=anythingllm_prod
DB_SSL=false

# AI 模型配置
OPENAI_API_KEY=your-production-openai-key
OPENAI_MODEL=gpt-4

# 向量数据库配置
CHROMA_ENDPOINT=http://chroma:8000
CHROMA_COLLECTION=anythingllm_prod

# 缓存配置
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=your-redis-password

# 存储配置
STORAGE_DIR=/app/storage

# 监控配置
MONITORING_ENABLED=true
LOG_LEVEL=info

# 邮件配置
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password

Nginx 配置

nginx
# nginx/nginx.conf
events {
    worker_connections 1024;
}

http {
    upstream anythingllm {
        server anythingllm:3001;
    }

    # HTTP 重定向到 HTTPS
    server {
        listen 80;
        server_name anythingllm.yourdomain.com;
        return 301 https://$server_name$request_uri;
    }

    # HTTPS 配置
    server {
        listen 443 ssl http2;
        server_name anythingllm.yourdomain.com;

        # SSL 证书配置
        ssl_certificate /etc/nginx/ssl/cert.pem;
        ssl_certificate_key /etc/nginx/ssl/key.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
        ssl_prefer_server_ciphers off;

        # 安全头
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";

        # 代理配置
        location / {
            proxy_pass http://anythingllm;
            proxy_set_header Host $host;
            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;
            
            # WebSocket 支持
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            
            # 超时配置
            proxy_connect_timeout 60s;
            proxy_send_timeout 60s;
            proxy_read_timeout 60s;
        }

        # 静态文件缓存
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
            proxy_pass http://anythingllm;
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        # 健康检查
        location /health {
            proxy_pass http://anythingllm/health;
            access_log off;
        }
    }
}

数据库初始化脚本

sql
-- init-scripts/01-init.sql
-- 创建数据库和用户
CREATE DATABASE anythingllm;
CREATE USER anythingllm WITH ENCRYPTED PASSWORD 'anythingllm_password';
GRANT ALL PRIVILEGES ON DATABASE anythingllm TO anythingllm;

-- 连接到 anythingllm 数据库
\c anythingllm;

-- 创建扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";

-- 设置权限
GRANT ALL ON SCHEMA public TO anythingllm;

生产环境部署

使用 Docker Swarm

yaml
# docker-stack.yml
version: '3.8'

services:
  anythingllm:
    image: mintplexlabs/anythingllm:latest
    ports:
      - "3001:3001"
    volumes:
      - anythingllm_storage:/app/storage
    environment:
      - NODE_ENV=production
      - JWT_SECRET=your-super-secret-jwt-key
      - DATABASE_TYPE=postgres
      - DB_HOST=postgres
    deploy:
      replicas: 3
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
      resources:
        limits:
          cpus: '2'
          memory: 4G
        reservations:
          cpus: '1'
          memory: 2G
    networks:
      - anythingllm_network

  postgres:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=anythingllm
      - POSTGRES_USER=anythingllm
      - POSTGRES_PASSWORD=anythingllm_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == manager
    networks:
      - anythingllm_network

volumes:
  anythingllm_storage:
    driver: local
  postgres_data:
    driver: local

networks:
  anythingllm_network:
    driver: overlay
    attachable: true
bash
# 部署到 Swarm
docker stack deploy -c docker-stack.yml anythingllm

# 查看服务状态
docker service ls

# 扩展服务
docker service scale anythingllm_anythingllm=5

# 更新服务
docker service update --image mintplexlabs/anythingllm:v2.0.0 anythingllm_anythingllm

# 删除堆栈
docker stack rm anythingllm

使用 Kubernetes

yaml
# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: anythingllm

---
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: anythingllm-config
  namespace: anythingllm
data:
  NODE_ENV: "production"
  SERVER_PORT: "3001"
  DATABASE_TYPE: "postgres"
  DB_HOST: "postgres"
  DB_PORT: "5432"
  DB_NAME: "anythingllm"

---
# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: anythingllm-secrets
  namespace: anythingllm
type: Opaque
stringData:
  JWT_SECRET: "your-super-secret-jwt-key"
  OPENAI_API_KEY: "your-openai-api-key"
  DB_USERNAME: "anythingllm"
  DB_PASSWORD: "anythingllm_password"

---
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: anythingllm
  namespace: anythingllm
spec:
  replicas: 3
  selector:
    matchLabels:
      app: anythingllm
  template:
    metadata:
      labels:
        app: anythingllm
    spec:
      containers:
      - name: anythingllm
        image: mintplexlabs/anythingllm:latest
        ports:
        - containerPort: 3001
        envFrom:
        - configMapRef:
            name: anythingllm-config
        - secretRef:
            name: anythingllm-secrets
        volumeMounts:
        - name: storage
          mountPath: /app/storage
        resources:
          requests:
            memory: "2Gi"
            cpu: "1"
          limits:
            memory: "4Gi"
            cpu: "2"
        livenessProbe:
          httpGet:
            path: /health
            port: 3001
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /health
            port: 3001
          initialDelaySeconds: 30
          periodSeconds: 10
      volumes:
      - name: storage
        persistentVolumeClaim:
          claimName: anythingllm-storage

---
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: anythingllm-service
  namespace: anythingllm
spec:
  selector:
    app: anythingllm
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3001
  type: ClusterIP

---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: anythingllm-ingress
  namespace: anythingllm
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - anythingllm.yourdomain.com
    secretName: anythingllm-tls
  rules:
  - host: anythingllm.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: anythingllm-service
            port:
              number: 80

---
# k8s/pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: anythingllm-storage
  namespace: anythingllm
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Gi
  storageClassName: fast-ssd
bash
# 部署到 Kubernetes
kubectl apply -f k8s/

# 查看部署状态
kubectl get pods -n anythingllm

# 查看日志
kubectl logs -f deployment/anythingllm -n anythingllm

# 扩展部署
kubectl scale deployment anythingllm --replicas=5 -n anythingllm

# 删除部署
kubectl delete -f k8s/

监控和日志

使用 Prometheus 和 Grafana

yaml
# monitoring/docker-compose.monitoring.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
      - '--storage.tsdb.retention.time=200h'
      - '--web.enable-lifecycle'
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_USERS_ALLOW_SIGN_UP=false
    restart: unless-stopped

  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.rootfs=/rootfs'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    restart: unless-stopped

volumes:
  prometheus_data:
  grafana_data:

日志聚合

yaml
# logging/docker-compose.logging.yml
version: '3.8'

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.8.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data

  logstash:
    image: docker.elastic.co/logstash/logstash:8.8.0
    container_name: logstash
    volumes:
      - ./logstash/pipeline:/usr/share/logstash/pipeline
    ports:
      - "5044:5044"
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:8.8.0
    container_name: kibana
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch

  filebeat:
    image: docker.elastic.co/beats/filebeat:8.8.0
    container_name: filebeat
    volumes:
      - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    depends_on:
      - logstash

volumes:
  elasticsearch_data:

备份和恢复

数据备份脚本

bash
#!/bin/bash
# backup.sh

# 配置
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)
COMPOSE_FILE="docker-compose.yml"

# 创建备份目录
mkdir -p $BACKUP_DIR

# 备份数据库
echo "备份数据库..."
docker-compose exec -T postgres pg_dump -U anythingllm anythingllm > $BACKUP_DIR/postgres_$DATE.sql

# 备份应用数据
echo "备份应用数据..."
docker run --rm \
  -v anythingllm_storage:/data \
  -v $BACKUP_DIR:/backup \
  alpine tar czf /backup/storage_$DATE.tar.gz -C /data .

# 备份向量数据库
echo "备份向量数据库..."
docker run --rm \
  -v chroma_data:/data \
  -v $BACKUP_DIR:/backup \
  alpine tar czf /backup/chroma_$DATE.tar.gz -C /data .

# 清理旧备份(保留7天)
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete

echo "备份完成: $BACKUP_DIR"

数据恢复脚本

bash
#!/bin/bash
# restore.sh

# 配置
BACKUP_DIR="/backups"
BACKUP_DATE=$1

if [ -z "$BACKUP_DATE" ]; then
  echo "使用方法: $0 <backup_date>"
  echo "例如: $0 20231201_120000"
  exit 1
fi

# 停止服务
echo "停止服务..."
docker-compose down

# 恢复数据库
echo "恢复数据库..."
docker-compose up -d postgres
sleep 10
docker-compose exec -T postgres psql -U anythingllm -d anythingllm < $BACKUP_DIR/postgres_$BACKUP_DATE.sql

# 恢复应用数据
echo "恢复应用数据..."
docker run --rm \
  -v anythingllm_storage:/data \
  -v $BACKUP_DIR:/backup \
  alpine sh -c "cd /data && tar xzf /backup/storage_$BACKUP_DATE.tar.gz"

# 恢复向量数据库
echo "恢复向量数据库..."
docker run --rm \
  -v chroma_data:/data \
  -v $BACKUP_DIR:/backup \
  alpine sh -c "cd /data && tar xzf /backup/chroma_$BACKUP_DATE.tar.gz"

# 启动所有服务
echo "启动服务..."
docker-compose up -d

echo "恢复完成"

故障排除

常见问题

容器启动失败

bash
# 查看容器日志
docker logs anythingllm

# 检查容器状态
docker ps -a

# 检查资源使用
docker stats

# 重启容器
docker restart anythingllm

数据库连接问题

bash
# 检查数据库容器状态
docker-compose ps postgres

# 测试数据库连接
docker-compose exec postgres psql -U anythingllm -d anythingllm -c "SELECT 1;"

# 查看数据库日志
docker-compose logs postgres

性能问题

bash
# 检查资源使用
docker stats

# 检查磁盘空间
df -h

# 清理未使用的镜像和容器
docker system prune -a

# 查看容器资源限制
docker inspect anythingllm | grep -A 10 "Resources"

调试工具

bash
# 进入容器调试
docker exec -it anythingllm /bin/bash

# 查看容器网络
docker network ls
docker network inspect anythingllm_default

# 检查端口占用
netstat -tulpn | grep :3001

# 测试服务可用性
curl -f http://localhost:3001/health

使用 Docker 部署 AnythingLLM 提供了一致的运行环境和简化的管理方式。根据您的需求选择合适的部署方案,并定期进行备份和监控以确保系统稳定运行。

AnythingLLM 是一个功能强大的开源 AI 知识管理平台,支持多种 LLM 模型,让您轻松构建智能对话系统和知识库。