基于docker容器化部署智能体AI agent

2 阅读13分钟

前言

上篇文章我们已经讲过如何从0开始搭建一个AI agent,今天我们再来具体操作如何将你的智能体部署到服务器,实现线上访问。

适用场景: CentOS 7 + Docker + Nginx 反向代理
服务器配置: 最低 2 核 CPU / 2GB 内存
部署架构: FastAPI 后端 + Streamlit 前端 + Chroma 向量数据库


目录


部署架构概览

技术栈

组件技术选型说明
后端框架FastAPI + Uvicorn异步 Web 框架,支持 SSE 流式响应
前端界面Streamlit快速构建交互式 Web 应用
向量数据库ChromaDB本地持久化向量存储
LLM 服务阿里云 DashScope通义千问大模型 API
容器化Docker + Docker Compose统一运行环境
反向代理Nginx处理 HTTP 请求转发和 SSE 流式传输

数据持久化

  • 向量数据库: ./chroma_db./rag/chroma_db 挂载到容器
  • 知识库文件: ./data 目录存放 PDF/TXT 原始文档
  • 日志文件: ./logs 目录记录运行日志
  • 环境变量: .env 文件只读挂载,保护敏感信息

第一步:本地环境准备

1.1 确认项目依赖

创建依赖文件 requirements.txt 根据项目情况检查是否包含核心依赖,以下以我自己的agent为例:

fastapi
uvicorn[standard]
langchain
langchain-core
langchain-community
langchain-chroma
langchain-text-splitters
dashscope
chromadb
pypdf
pydantic
python-dotenv
pyyaml
loguru
streamlit

1.2 创建 Dockerfile

在项目根目录创建 Dockerfile,定义容器镜像构建规则:

FROM python:3.11-slim
WORKDIR /app

# 安装系统依赖(编译工具和 OpenMP 库)
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential libgomp1 \
    && rm -rf /var/lib/apt/lists/* && apt-get clean

# 安装 Python 依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt && pip cache purge

# 复制项目代码
COPY . .

# 创建必要的目录
RUN mkdir -p /app/chroma_db /app/rag/chroma_db /app/logs

# 暴露端口
EXPOSE 8000 8501

# 默认启动命令(docker-compose 会覆盖此命令)
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]

1.3 创建 docker-compose.yml

在项目根目录创建 docker-compose.yml,定义服务编排配置:

services:
  learn-agent:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: learn-agent
    ports:
      - "8000:8000"      # FastAPI 后端
      - "8501:8501"      # Streamlit 前端
    volumes:
      - ./chroma_db:/app/chroma_db
      - ./rag/chroma_db:/app/rag/chroma_db
      - ./data:/app/data
      - ./logs:/app/logs
      - ./.env:/app/.env:ro
    dns:
      - 223.6.6.6        # 阿里云公共 DNS
      - 8.8.8.8          # Google 公共 DNS
    command: >
      sh -c "uvicorn api.main:app --host 0.0.0.0 --port 8000 &
             streamlit run app.py --server.address 0.0.0.0 --server.port 8501"
    restart: unless-stopped
    mem_limit: 1500m     # 内存限制
    cpus: 1.5            # CPU 限制

关键配置说明:

  • dns 配置: 解决容器内无法解析 dashscope.aliyuncs.com 的问题
  • command 覆盖: 同时启动 FastAPI 和 Streamlit 两个服务
  • 资源限制: 适配 2GB 内存服务器,预留 500MB 给系统

1.4 创建 .dockerignore

在项目根目录创建 .dockerignore,排除不需要打包的文件:

__pycache__/
*.pyc
.venv/
.env
.idea/
.git/
logs/
node_modules/
frontend/
chroma_db/
rag/chroma_db/

排除原因:

  • chroma_db/rag/chroma_db/:向量库文件在服务器上重新生成,避免文件锁定问题
  • .env:包含敏感信息,单独上传
  • frontend/:前端独立部署,不放入后端容器

1.5 打包并上传到服务器

方式一:使用 PowerShell 压缩

# 在项目根目录执行
Compress-Archive -Path * -DestinationPath deploy.zip -Force

方式二:使用 7-Zip 或 WinRAR

手动压缩时,确保排除 .dockerignore 中列出的目录和文件。

上传到服务器:

# 在本地 Git Bash 或 PowerShell 执行
scp D:/PythonProject/你的智能体项目文件夹/deploy.zip root@你的服务器IP:/root/

第二步:服务器环境部署

2.1 更新系统软件包

sudo yum update -y

2.2 安装 Docker CE

卸载旧版本(如有):

sudo yum remove -y docker docker-client docker-client-latest \
    docker-common docker-latest docker-latest-logrotate \
    docker-logrotate docker-engine

添加阿里云 Docker CE 镜像源:

国内网络环境下,使用阿里云镜像源可显著提升下载速度。

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装 Docker CE 及 Docker Compose 插件:

sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

2.3 配置 Docker 守护进程

创建 /etc/docker/daemon.json 配置文件:

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json > /dev/null << 'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://docker.xuanyuan.me",
    "https://mirror.ccs.tencentyun.com"
  ],
  "iptables": true
}
EOF

配置说明:

  • registry-mirrors 配置 Docker Hub 镜像加速,解决国内访问超时问题
  • iptables: true 允许 Docker 管理 iptables 规则,避免与 firewalld 冲突

2.4 关闭系统防火墙

CentOS 7 默认启用 firewalld,与 Docker 的 iptables 规则存在冲突,会导致容器端口映射失败。

sudo systemctl stop firewalld
sudo systemctl disable firewalld

错误示例(未关闭防火墙时):

iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8000 
-j DNAT --to-destination 172.18.0.2:8000 ! -i br-512396465b1d: 
iptables: No chain/target/match by that name.

2.5 启动 Docker 服务

sudo systemctl daemon-reload
sudo systemctl start docker
sudo systemctl enable docker

验证安装:

sudo docker run --rm hello-world

看到 Hello from Docker! 即表示安装成功。

2.6 解压项目文件

cd /root
unzip deploy.zip -d /data/shier_agent
cd /data/shier_agent

2.7 上传环境变量文件

重要: 不要在服务器上手动创建 .env 文件,使用 heredoc 粘贴内容会导致编码损坏。

在本地执行:

scp D:/PythonProject/你的项目文件夹/.env root@你的服务器IP:/data/shier_agent/.env

在服务器上验证:

cat /data/shier_agent/.env

确认内容格式正确,无乱码:

ANTHROPIC_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
ANTHROPIC_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
LANGSMITH_API_KEY=lsv2_pt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ZHIPU_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python

2.8 创建必要的目录

mkdir -p /data/shier_agent/data
mkdir -p /data/shier_agent/logs
mkdir -p /data/shier_agent/chroma_db
mkdir -p /data/shier_agent/rag/chroma_db

2.9 配置系统 Swap

2GB 内存服务器建议开启 Swap,防止容器因内存不足被 OOM Kill。

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

验证 Swap 状态:

free -h

输出示例:

              total        used        free      shared  buff/cache   available
Mem:           1.8G        800M        200M         10M        800M        900M
Swap:          2.0G          0B        2.0G

2.10 清理旧容器和网络

如果之前有启动失败的容器,需先清理:

cd /data/shier_agent
sudo docker ps -a | grep learn-agent
sudo docker rm -f learn-agent 2>/dev/null
sudo docker network prune -f

2.11 构建 Docker 镜像

cd /data/shier_agent
sudo docker compose build

注意: 首次构建需要下载 Python 基础镜像(约 150MB)和安装依赖包,耗时约 20~40 分钟,请耐心等待。

2.12 启动容器

sudo docker compose up -d

2.13 查看启动日志

sudo docker compose logs -f

成功启动的标志:

learn-agent  | INFO:     Application startup complete.
learn-agent  | INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
learn-agent  | 
learn-agent  |   You can now view your Streamlit app in your browser.
learn-agent  | 
learn-agent  |   Local URL: http://localhost:8501
learn-agent  |   Network URL: http://172.18.0.2:8501

Ctrl+C 退出日志查看。

2.14 安装 Nginx

sudo yum install -y nginx

2.15 配置 Nginx 反向代理

使用 sudo tee 直接写入配置文件(CentOS 7 默认无 nano 编辑器):

sudo tee /etc/nginx/nginx.conf > /dev/null << 'EOF'
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;

    upstream api_backend {
        server 127.0.0.1:8000;
    }

    server {
        listen 80;
        server_name _;

        # FastAPI 后端 - SSE 流式对话接口
        location /api/ {
            proxy_pass http://api_backend;
            proxy_http_version 1.1;
            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;
            proxy_set_header Connection '';
            proxy_buffering off;           # 关键:禁用缓冲,支持 SSE 流式传输
            proxy_cache off;
            chunked_transfer_encoding on;
        }

        # 健康检查接口
        location /health {
            proxy_pass http://api_backend;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # Streamlit 前端
        location / {
            proxy_pass http://127.0.0.1:8501;
            proxy_http_version 1.1;
            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;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;      # WebSocket 长连接超时时间
            proxy_buffering off;
        }
    }
}
EOF

配置要点:

  • SSE 流式传输: proxy_buffering offchunked_transfer_encoding on 确保实时响应
  • WebSocket 支持: UpgradeConnection 头部支持 Streamlit 的 WebSocket 连接
  • 长连接超时: proxy_read_timeout 86400 设置为 24 小时,避免长时间对话中断

2.16 启动 Nginx

sudo nginx -t                    # 验证配置文件语法
sudo systemctl start nginx       # 启动服务
sudo systemctl enable nginx      # 设置开机自启

2.17 配置防火墙(可选)

由于步骤 2.4 已关闭 firewalld,此步骤可跳过。如需使用 firewalld,执行:

sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --reload

2.18 配置云服务器安全组

登录阿里云控制台,配置 ECS 实例安全组:

  1. 进入 云服务器 ECS实例安全组
  2. 点击 配置规则添加入方向规则
  3. 填写规则:
    • 端口范围: 80/80
    • 授权对象: 0.0.0.0/0
    • 协议类型: TCP
    • 描述: HTTP 服务

第三步:部署验证

3.1 服务器本地验证

# 1. 检查 Docker 容器状态
sudo docker ps

# 2. 验证 FastAPI 后端
curl http://127.0.0.1:8000/health

# 3. 验证 Streamlit 前端
curl http://127.0.0.1:8501

# 4. 验证 Nginx 代理
curl http://127.0.0.1/health

预期输出:

{"status":"healthy"}

3.2 浏览器访问验证

服务访问地址说明
Streamlit 前端http://你的服务器IP/智能客服对话界面
API 健康检查http://你的服务器IP/health返回 {"status":"healthy"}
RAG 检索测试http://你的服务器IP/api/rag/retrieve?query=测试&top_k=3测试向量检索功能

3.3 上传知识库并验证 RAG

如果 RAG 检索返回 {"documents": [], "count": 0},说明知识库未加载。

步骤一:上传知识库文件

# 在本地执行
scp -r D:/PythonProject/你的项目文件夹/data/* root@你的服务器IP:/data/shier_agent/data/

步骤二:触发知识库重载

curl -X POST http://你的服务器IP:8000/api/knowledge/reload

步骤三:查看重载状态

curl http://你的服务器IP:8000/api/knowledge/reload/status

步骤四:验证检索功能

curl "http://你的服务器IP:8000/api/rag/retrieve?query=怎么保养扫地机器人&top_k=3"

成功响应示例:

{
  "query": "怎么保养扫地机器人",
  "documents": [
    {
      "content": "定期清理尘盒和滤网...",
      "metadata": {"source": "manual.pdf", "page": 12}
    }
  ],
  "count": 3
}

第四步:项目更新流程

4.1 本地代码修改后上传

方式一:分模块上传(推荐)

适用于小范围代码变更,上传速度快:

# 在本地执行,仅上传变更的模块
scp -r D:/PythonProject/你的项目文件夹/api root@你的服务器IP:/data/shier_agent/
scp -r D:/PythonProject/你的项目文件夹/agent root@你的服务器IP:/data/shier_agent/
scp -r D:/PythonProject/你的项目文件夹/rag root@你的服务器IP:/data/shier_agent/
scp -r D:/PythonProject/你的项目文件夹/model root@你的服务器IP:/data/shier_agent/
scp -r D:/PythonProject/你的项目文件夹/config root@你的服务器IP:/data/shier_agent/
scp -r D:/PythonProject/你的项目文件夹/utils root@你的服务器IP:/data/shier_agent/
scp D:/PythonProject/你的项目文件夹/app.py root@你的服务器IP:/data/shier_agent/

方式二:完整同步(适用于大量文件变更)

# 在本地执行
rsync -avz --exclude='chroma_db' --exclude='rag/chroma_db' \
  --exclude='logs' --exclude='__pycache__' --exclude='frontend' \
  --exclude='node_modules' --exclude='.venv' --exclude='.git' \
  --exclude='*.pyc' --exclude='.env' \
  D:/PythonProject/你的项目文件夹/ root@你的服务器IP:/data/shier_agent/

4.2 服务器上重新构建并启动

cd /data/shier_agent
sudo docker compose down          # 停止旧容器
sudo docker compose up -d --build # 重新构建并启动
sudo docker compose logs -f       # 查看启动日志

4.3 验证更新

# API 健康检查
curl http://127.0.0.1:8000/health

# Streamlit 页面
curl http://127.0.0.1:8501

常见问题排查

Q1: iptables: No chain/target/match by that name

错误现象:

Error response from daemon: driver failed programming external connectivity 
on endpoint learn_agent: iptables failed: iptables --wait -t nat -A DOCKER 
-p tcp -d 0/0 --dport 8000 -j DNAT --to-destination 172.18.0.2:8000 
! -i br-512396465b1d: iptables: No chain/target/match by that name.

原因分析:

CentOS 7 默认启用 firewalld,与 Docker 的 iptables 规则冲突。

解决方案:

sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo systemctl restart docker
cd /data/shier_agent
sudo docker compose down
sudo docker compose up -d

Q2: Failed to resolve 'dashscope.aliyuncs.com'

错误现象:

{
  "detail": "HTTPSConnectionPool(host='dashscope.aliyuncs.com', port=443): 
  Max retries exceeded with url: /api/v1/services/embeddings/text-embedding/text-embedding 
  (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection object at 0x7f8b3c0a0d90>: 
  Failed to resolve 'dashscope.aliyuncs.com' ([Errno -3] Temporary failure in name resolution)"))"
}

原因分析:

Docker 容器内 DNS 配置缺失,无法解析阿里云域名。

解决方案:

确认 docker-compose.yml 中包含以下配置:

dns:
  - 223.6.6.6
  - 8.8.8.8

如没有,补充后重建容器:

cd /data/shier_agent
sudo docker compose down
sudo docker compose up -d --build

Q3: RAG 检索返回空结果

错误现象:

{
  "query": "怎么保养扫地机器人",
  "documents": [],
  "count": 0
}

原因分析:

服务器上 data/ 目录为空,知识库未加载。

解决方案:

参考 第三步 3.3 上传知识库文件并触发重载。


Q4: .env 文件内容乱码或 API 密钥不生效

错误现象:

  • API 调用返回 401 Unauthorized
  • 日志中显示 ANTHROPIC_API_KEY 为空或乱码

原因分析:

在服务器上通过 heredoc 粘贴 .env 内容时,中文字符或特殊符号导致编码损坏。

解决方案:

# 删除损坏的文件
sudo rm -f /data/shier_agent/.env

# 从本地上传正确的 .env
scp D:/PythonProject/你的项目文件夹/.env root@你的服务器IP:/data/shier_agent/.env

# 重启容器使新配置生效
cd /data/shier_agent
sudo docker compose restart

Q5: Docker 构建速度慢

现象:

docker compose build 执行时间超过 30 分钟。

原因分析:

  • 国内网络访问 Docker Hub 速度慢
  • Python 依赖包下载速度慢

解决方案:

  1. 确认 /etc/docker/daemon.json 中已配置镜像加速
  2. 耐心等待,首次构建需要下载基础镜像和依赖包
  3. 如果超过 1 小时仍未完成,检查网络连接

附录

A.1 环境变量说明

变量名说明必填
ANTHROPIC_BASE_URL阿里云 DashScope API 地址
ANTHROPIC_API_KEYDashScope API 密钥
LANGSMITH_API_KEYLangSmith 追踪密钥
ZHIPU_API_KEY智谱 AI API 密钥
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATIONProtobuf 实现方式

A.2 常用运维命令

# 查看容器状态
sudo docker ps

# 查看容器日志
sudo docker compose logs -f

# 重启容器
sudo docker compose restart

# 停止容器
sudo docker compose down

# 查看容器资源占用
sudo docker stats learn-agent

# 进入容器内部
sudo docker exec -it learn-agent bash

# 查看 Nginx 日志
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log

A.3 性能优化建议

针对 2GB 内存服务器:

  1. 调整 Uvicorn workers: 保持 --workers 1,避免多进程占用过多内存
  2. 限制 ChromaDB 缓存:config/chroma.yml 中设置合理的 chunk_size
  3. 定期清理日志: 设置日志轮转,避免磁盘占满
# 清理 Docker 日志
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"

# 清理应用日志
sudo find /data/shier_agent/logs -name "*.log" -mtime +7 -delete

A.4 安全加固建议

  1. 修改 SSH 默认端口: 编辑 /etc/ssh/sshd_config,将 Port 22 改为其他端口
  2. 禁用 root 远程登录: 设置 PermitRootLogin no
  3. 配置 HTTPS: 使用 Let's Encrypt 申请免费 SSL 证书
  4. 限制 API 访问频率: 在 FastAPI 中集成 slowapi 限流中间件

总结

本文档详细介绍了智扫通机器人在 CentOS 7 + Docker 环境下的完整部署流程,涵盖了从本地准备到服务器部署、验证和更新的全过程。通过遵循本指南,您可以快速搭建一个稳定可靠的生产环境。

如遇到文档中未涵盖的问题,请参考项目 GitHub Issues 或联系技术支持。