目录

前言

1. 问题解析

2. 解决方案对比与选择

3. 各方案具体配置步骤

3.1 方案一:优化启动脚本 (init_models.sh)

3.2 方案二:配置Systemd服务

3.3 方案三:调整Docker启动参数

4. 行动建议与验证


前言

在某台ubuntu系统的机器上部署了dify和ollama服务,使用下述命令启动的ollama服务:

sudo docker run -d --gpus=all -v /dify_workspace/ollama_weights:/root/.ollama -v /dify_workspace/ollama_weights/init_models.sh:/init_models.sh -p 11434:11434 --network host --restart=always --name ollama --entrypoint /bin/sh ollama/ollama:latest /init_models.sh

问题:机器重启之后,ollama服务中加载的模型还是跑在cpu上,还必须再执行sudo docker restart ollama命令,然后模型才能使用GPU运行。

init_models.sh文件的内容如下:

#!/bin/sh

# 后台启动 ollama 服务
ollama serve &

# 等待服务就绪,通过尝试列出模型来检查
# sleep 5
max_attempts=30
attempt=1
until ollama list >/dev/null 2>&1; do
  if [ $attempt -eq $max_attempts ]; then
    echo "错误:等待Ollama服务启动超时"
    exit 1
  fi
  sleep 2
  attempt=$((attempt + 1))
done

# 模型预加载(不会输出内容)
ollama run qwen2.5:14b "warmup" >/dev/null 2>&1
# ollama run shaw/dmeta-embedding-zh:latest "warmup" >/dev/null 2>&1
ollama run lrs33/bce-embedding-base_v1:latest "warmup" >/dev/null 2>&1

# 保持前台运行
wait

1. 问题解析

根据描述的情况,Ollama容器在主机重启后能自动运行,但GPU却无法正常使用,这通常是由于Ollama服务的启动速度快于主机上NVIDIA GPU驱动的初始化所导致的时序问题。

简单来说,当你的启动脚本开始检查Ollama是否就绪时,GPU环境可能还未准备好,导致后续加载的模型都默认使用了CPU。

2. 解决方案对比与选择

你可以从以下几个方案中选择适合你的解决路径,它们各有侧重点:

方案 核心思路 优点 缺点 推荐场景
方案一:优化启动脚本 在脚本中增加对GPU驱动的就绪检查。 改动小,直接针对问题根源。 依赖脚本逻辑,可能与Docker的重启策略存在时序竞争。 作为快速验证和补充方案。
方案二:使用Systemd服务 通过Systemd确保GPU就绪后再启动容器。 启动顺序可控,Linux系统原生支持。 需要额外配置Systemd单元文件。 生产环境首选,确保稳定性。
方案三:调整Docker配置 为容器添加必要的环境和权限参数。 配置集中在Docker层面,管理方便。 不直接解决主机驱动时序问题。

3. 各方案具体配置步骤

3.1 方案一:优化启动脚本 (init_models.sh)

在脚本中ollama serve &命令之后,增加对GPU驱动就绪的检查。可以将下面这段代码插入到“等待服务就绪”的循环之前:

# 新增:等待NVIDIA驱动和GPU设备就绪
max_gpu_attempts=30
gpu_attempt=1
until nvidia-smi >/dev/null 2>&1; do
    if [ $gpu_attempt -eq $max_gpu_attempts ]; then
        echo "错误:等待NVIDIA GPU驱动就绪超时"
        exit 1
    fi
    sleep 2
    gpu_attempt=$((gpu_attempt + 1))
done
echo "NVIDIA GPU驱动已就绪。"

3.2 方案二:配置Systemd服务

这个方法可以让系统在网络和基本服务启动后,再启动你的Ollama容器,给GPU驱动留出足够的初始化时间。

1. 创建Systemd服务文件

使用以下命令创建并编辑文件:

sudo nano /etc/systemd/system/ollama-docker.service

2. 编写服务配置

将以下内容写入文件,注意替换其中 /dify_workspace 为你的实际路径:

[Unit]
Description=Ollama Docker Container with GPU
Requires=docker.service
After=docker.service network.target nvidia-persistenced.service
# 明确等待docker、网络和NVIDIA持久化服务
Wants=nvidia-persistenced.service

[Service]
Restart=always
ExecStartPre=/usr/bin/docker stop ollama 2>/dev/null || true
ExecStartPre=/usr/bin/docker rm ollama 2>/dev/null || true
# 启动命令(已整合了你原有的docker run参数)
ExecStart=/usr/bin/docker run -d --gpus=all \
    -v /dify_workspace/ollama_weights:/root/.ollama \
    -v /dify_workspace/ollama_weights/init_models.sh:/init_models.sh \
    -p 11434:11434 \
    --network host \
    --name ollama \
    --entrypoint /bin/sh \
    ollama/ollama:latest \
    /init_models.sh

ExecStop=/usr/bin/docker stop ollama

[Install]
WantedBy=multi-user.target

3. 启用并启动服务

依次执行以下命令:

sudo systemctl daemon-reload
sudo systemctl enable ollama-docker.service  # 设置开机自启
sudo systemctl start ollama-docker.service   # 立即启动服务
sudo systemctl status ollama-docker.service  # 检查状态

3.3 方案三:调整Docker启动参数

在现有或新的 docker run 命令中,确保添加了正确的GPU和环境变量参数,这是GPU能正确挂载的基础。

# 关键参数示例,请整合到你的命令中
--gpus all \
--runtime=nvidia \
-e NVIDIA_VISIBLE_DEVICES=all \
-e NVIDIA_DRIVER_CAPABILITIES=compute,utility \

4. 行动建议与验证

综合以上方案,我为你梳理出一条清晰的解决路径:

  1. 立即验证(快速方案):先执行 方案三,确保你的 docker run 命令包含了完整的GPU参数。这是最基础的检查。

  2. 根本解决(推荐方案):优先实施 方案二(Systemd服务),因为它能从系统层面最可靠地解决启动时序问题。在配置Systemd时,可以将 方案一 中对GPU的检查脚本也整合进去,作为双重保障。

  3. 验证效果:配置完成后,重启你的Ubuntu主机。等待几分钟后,通过以下命令检查是否成功:

    • 检查容器状态docker ps

    • 检查GPU是否被容器识别docker exec ollama nvidia-smi 或 docker exec ollama bash -c "ollama run qwen2.5:14b 'hello'" 并观察日志是否提示使用GPU。

如果按照方案二配置Systemd,在后续的重启中,系统就会自动按正确顺序启动服务。如果重启后问题依然存在,可以执行 sudo systemctl status ollama-docker.service 和 docker logs ollama 这两个命令查看输出结果,进行进一步分析。


Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐