主数据模型Docker部署指南

📦 第一部分:安装Docker

1.1 清理旧版本

# 这条命令会删除所有可能存在的旧版Docker组件
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
    sudo apt-get remove $pkg -y
done

1.2 添加官方软件源

# 更新软件列表(相当于刷新应用商店)
sudo apt-get update

# 安装基础工具包
sudo apt-get install ca-certificates curl -y

# 创建安全密钥目录(给Docker的"身份证"准备位置)
sudo install -m 0755 -d /etc/apt/keyrings

# 下载并安装Docker的"身份证"
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# 添加软件源地址(告诉系统去哪里下载Docker)
echo \
  "deb [arch=(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu \(. /etc/os-release && echo "${UBUNTU_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 再次更新软件列表
sudo apt-get update

1.3 安装Docker全家桶

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

1.4 测试安装是否成功

(运行Hello World测试)

sudo docker run --rm hello-world

🔍 看到”Hello from Docker!”说明安装成功!

1.5 免sudo使用Docker

(避免每次都要输入密码)

# 将当前用户加入docker用户组
sudo usermod -aG docker $USER

# 重要提示框
echo "⚠️ 需要注销并重新登录才能生效!"
echo "现在请关闭所有窗口,重新打开终端!"

🎮 第二部分:安装NVIDIA支持

2.1 添加NVIDIA软件源

# 下载并安装NVIDIA的"身份证"
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

# 添加NVIDIA软件源地址
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
    sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

2.2 安装工具包

sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

2.3 配置Docker

sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

📡 第三部分:API接口开发(以BERT为例)

3.1 创建API服务文件 server.py

(在项目code目录下创建)

from flask import Flask, request, jsonify
import torch
from transformers import BertTokenizer, BertModel
import logging
import os

# 初始化Flask应用
app = Flask(__name__)

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 错误处理类
class APIError(Exception):
    def __init__(self, message, status_code=400):
        self.message = message
        self.status_code = status_code

# 加载模型和分词器
def load_model():
    try:
        model_path = "/app/model/bert-base-uncased"  # 模型路径
        tokenizer = BertTokenizer.from_pretrained(model_path)
        model = BertModel.from_pretrained(model_path)
        return tokenizer, model
    except Exception as e:
        raise APIError(f"模型加载失败: {str(e)}", 500)

tokenizer, model = load_model()

@app.route('/api/generate', methods=['POST'])
def generate_text():
    try:
        # 检查输入数据
        if not request.is_json:
            raise APIError("请求必须为JSON格式", 400)

        data = request.get_json()
        if 'text' not in data or not isinstance(data['text'], str):
            raise APIError("缺少或无效的'text'字段", 400)

        # 调用模型处理文本
        inputs = tokenizer(data['text'], return_tensors="pt", padding=True, truncation=True)
        with torch.no_grad():
            outputs = model(**inputs)

        # 获取模型输出
        last_hidden_states = outputs.last_hidden_state
        embeddings = last_hidden_states.mean(dim=1).squeeze().tolist()

        # 返回JSON响应
        return jsonify({
            "status": "success",
            "result": embeddings
        })

    except APIError as e:
        logger.error(f"API错误: {e.message}")
        return jsonify({"status": "error", "message": e.message}), e.status_code

    except Exception as e:
        logger.error(f"服务器内部错误: {str(e)}")
        return jsonify({"status": "error", "message": "服务器内部错误"}), 500

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=1480, debug=False)

3.2 代码结构说明

Docker_build/
├── code/
│   ├── server.py       # API服务主文件
│   └── requirements.txt # Python依赖列表
├── model/
│   └── bert-base-uncased/  # BERT模型文件
└── Dockerfile

3.3 更新requirements.txt

flask>=2.0.1
torch>=1.10.0
transformers>=4.12.0

3.4 API测试方法

使用curl测试

curl -X POST http://localhost:1480/api/generate \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello, how are you?"}'

预期成功响应

{
  "status": "success",
  "result": [0.123, -0.456, 0.789, ...]  # 实际输出为768维向量
}

错误测试示例

# 发送无效JSON
curl -X POST http://localhost:1480/api/generate -d "invalid json"

# 预期响应
{
  "message": "请求必须为JSON格式",
  "status": "error"
}

3.5 API关键功能解析

3.5.1 错误处理机制

错误类型 处理方式 HTTP状态码
非JSON请求 返回格式错误提示 400
缺少必要字段 提示字段缺失 400
模型加载失败 记录日志并返回服务不可用 500
未知错误 通用错误提示 500

3.5.2 模型调用流程


🚢 第四部分:构建专属Docker镜像

4.1 准备项目文件夹

# 创建主文件夹(名字可以自己改)
mkdir -p ~/Docker_build

# 进入工作目录
cd ~/Docker_build

# 创建两个子文件夹(代码和模型分开放)
mkdir -p code   # 存放你的Python代码
mkdir -p model  # 存放AI模型文件

# 创建重要文件
touch Dockerfile       # 镜像说明书
touch start_srv.sh    # 启动脚本

4.2 编写Dockerfile

# 基础镜像选择(这里选CUDA 12.4版本)
# 如果需要其他版本,可以去这里找:https://hub.docker.com/r/nvidia/cuda/tags
FROM nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04

# 设置容器工作目录
WORKDIR /app/code

# 安装必要工具(给容器装软件)
RUN apt update && \
    apt install -y htop vim nano && \
    rm -rf /var/lib/apt/lists/*

# 复制代码文件(把本地的code文件夹复制到容器里)
COPY code /app/code

# 复制模型文件(把本地的model文件夹复制到容器里)
COPY model /app/model

# 安装Python依赖(自动安装requirements.txt里的包)
RUN if [ -f requirements.txt ]; then \
        pip install -r requirements.txt && \
        pip cache purge; \
    fi

# 复制启动脚本
COPY start_srv.sh /start_srv.sh
RUN chmod +x /start_srv.sh

# 设置启动命令(容器启动后自动执行)
CMD ["/start_srv.sh"]

4.3 编写启动脚本

(start_srv.sh示例)

#!/bin/bash
# 简单启动脚本示例
echo "🟢 正在启动服务..."
python server.py

💡 请确保:
1. 你的代码中模型路径要写成/app/model/你的模型文件
2. 端口号与Docker运行时配置一致

🚀 第五部分:运行你的AI服务

5.1 构建镜像

# 在Docker_build目录执行(注意最后的点!)
docker build -t my-ai-service .

my-ai-service是你起的名字,可以自己改
🔍 参数解释:
-t:给镜像起名(这里叫my-ai-service)
. :表示使用当前目录的Dockerfile

5.2 启动容器

(运行你的应用)

docker run -d \
  --gpus all \               # 使用所有显卡
  -p 1480:1480 \             # 端口映射(本机端口:容器端口)
  --name my-ai-container \   # 容器名字
  my-ai-service              # 镜像名字

5.3 常用命令速查

操作 命令 说明
📜 查看镜像 docker images 列出所有已下载的镜像
🏃 启动容器 docker start 容器名 启动已停止的容器
⏹ 停止容器 docker stop 容器名 停止容器
🔍 查看日志 docker logs -f 容器名 实时查看日志
🖥 进入容器 docker exec -it 容器名 bash 进入容器的命令行
🗑 删除容器 docker rm -f 容器名 强制删除容器
🧹 清理空间 docker system prune -a 删除所有未使用的镜像

🚨 常见问题解答

Q:如何修改服务端口?
1. 修改docker run-p 新端口:容器端口
2. 代码中监听的端口也要同步修改

Q:模型文件应该放在哪里?
➔ 放在本地的~/Docker_build/model目录,会自动复制到容器的/app/model

Q:如何更新代码?
1. 修改本地code目录的文件
2. 重新执行docker build
3. 删除旧容器,创建新容器