使用 Docker 在本地运行 Deepseek!

2025-06-07

使用 Docker 在本地运行 Deepseek!

关于

如果你稍微关注一下人工智能新闻,你可能听说过Deepseek。这款中国研发的新型人工智能应用据称比市面上其他任何应用都要好得多。你可能也听说过一些关于中国应用收集用户信息的恐怖故事。

如果您也这么想,那么您可能正在寻找更好的替代方案。答案是:您可以在本地系统上构建 Deepseek 客户端,无需连接互联网即可运行。更棒的是,您可以在 Docker 中执行此操作,因此无需安装任何其他程序。听起来不错?如果是,请继续阅读!

我们正在构建什么

我们将使用 Docker 创建一个 Web 界面,您可以在其中向 Deepseek 提问。

📖 Docker 详解

为此,我们将创建两个应用程序:

  1. 使用 Ollama 构建的 Deepseek 端点
  2. 一个简单的静态网站,它调用端点并获取问题的答案。

当我们构建多个相互通信的应用程序时,我们可以使用Docker Compose在 Docker 中轻松完成此操作。

步骤

🏃‍♂️赶时间?只需克隆此存储库并按照 README 文件中的说明进行操作!

步骤 1:创建 docker-compose 文件

要使用 Docker Compose,我们首先需要在项目目录中创建一个新文件。如果您还没有创建项目目录,请创建一个新目录,并在其中创建一个名为 的新文件docker-compose.yml

💡 docker-compose.yml 文件是我们将描述两个应用程序的地方,以便我们可以运行它们。

第 2 步:添加第一个应用

现在我们已经创建了 Docker Compose 文件,接下来定义我们的第一个应用程序,Deepseek Ollama。在 Docker Compose 中,应用程序被称为“服务”,但本质上是相同的。

我们将通过 Deepseek Ollama 应用程序向 Deepseek 提问并获得答案。

💡什么是 Ollama? Ollama是一个轻量级框架,您可以在本地计算机上轻松运行开源框架,例如 Deepseek 或 Llama。

要将 Deepseek 端点添加到您的docker-compose.yml文件,请将其添加到文件中:

services:
  ollama:
    image: ollama/ollama
    volumes:
      - ./ollama-models:/root/.ollama
    ports:
      - 11434:11434
Enter fullscreen mode Exit fullscreen mode

🤔 这里发生了什么?

  • 这部分告诉 Docker Compose 创建一个名为“ollama”的容器
  • 该容器将基于名为 的图像(基本上是一个蓝图)ollama/ollama。这是预装了 Ollama 的图像,因此您无需执行任何其他操作!
  • volumes部分内容实际上会将我们稍后要安装的模型的所有数据保存到您的本地硬盘上。在容器中,所有这些数据都会被保存,/root/.ollama但一旦容器关闭,它们就会消失。这并非我们想要的。因此,容器目录中存储的任何内容都将永久存储在ollama-models项目根目录中。
  • 当 Ollama 应用启动并运行时,它将在11434容器内的端口上运行,而不是在您的计算机上运行,​​这意味着您将无法从浏览器访问它。为了解决这个问题,该ports部件将两个端口配对。

现在我们已经添加了 Ollama 端点,现在可以运行它,以便安装 Deepseek。为此,只需在终端中运行此 Docker Compose 命令:

docker compose up -d ollama
Enter fullscreen mode Exit fullscreen mode

现在转到您的浏览器并检查 Ollama 应用程序是否正在运行,方法是将浏览器指向此地址:

http://localhost:11434

您的浏览器应该显示“Ollama 正在运行”文本,如下所示:

带有一个浏览器窗口

步骤3:安装Deepseek

现在 Ollama 已经启动并运行,我们可以继续安装 Deepseek 模型了。只需运行以下 Docker Compose 命令即可:

docker compose exec ollama ollama pull deepseek-r1:7b
Enter fullscreen mode Exit fullscreen mode

🤔这里发生了什么?

  • Docker Compose 中的命令exec本质上是在给定容器(在本例中为容器)内运行任何命令。上面这行代码运行(执行)了安装 Deepseek 模型的ollama命令。该命令的基本结构如下ollama pull deepseek-r1:7bexecdocker compose exec <containerName> <command>

此命令将需要几分钟来安装(取决于模型的大小),但一旦完成,它应该ollama-models使用 Deepseek 模型所需的文件填充新目录。

💡 Deepseek 模型有很多不同的大小。在本例中,我选择了 7b(即 70 亿个参数),但您可以根据系统的性能选择更多或更少的参数。您可以在此处查看完整列表

步骤 4:创建网站

现在我们的 Deepseek 应用已经启动并运行,我们可以创建一个 Web 界面来提问。我们将使用 HTML、CSS 和 JavaScript 创建一个简单的网站。如下所示:

网站截图

方法如下:

HTML

HTML 将定义一个简单的页面,其中包含一个文本框、一个用于发送问题的按钮和一个用于回答的空间。

📖 HTML 解释

创建一个名为 的新目录web,并在其中创建一个名为 的新文件index.html。将此 HTML 粘贴到文件中:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My AI</title>
    <script src="showdown.min.js"></script>
    <script src="ollama.js"></script>
    <link rel="stylesheet" href="style.css" />
</head>
<body>
    <h1>🤖 Local Deepseek</h1>

    <textarea name="" id="question"></textarea>
    <button onclick="run()">Ask!</button>

    <div id="answer">

    </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

🤔这里发生了什么?

  • <head>HTML 部分,您会注意到我们链接到一个文件,style.css接下来我们将创建此文件来设计我们的网站。
  • 您还会注意到两个 Javascript 文件,ollama.js并且showdown.min.js.ollama.js将是我们与 Deepseek 对话的地方,并showdown.min.js使用 Showdown,这是一个用于将 Markdown(我们将从 Deepseek 返回的内容)转换为 HTML 的 Javascript 库。

CSS

📖 CSS 讲解

要设置页面样式,请创建一个名为的新文件style.css并粘贴以下 CSS:

body{
    width: 600px;
    margin: auto;
}

#question{
    display: block;
    width: 100%;
    padding: 9px;
    font-size: 15px;
}

#answer{
    font-family: Arial, Helvetica, sans-serif;
    font-size: 15px;
    margin-top: 30px;
    line-height: 1.5;
}

#answer #think{
    border-left: 3px solid #eee;
    padding-left: 9px;
    color: #aaa;
    font-style: italic;
}
Enter fullscreen mode Exit fullscreen mode

JavaScript

📖 Javascript 解释

现在我们要创建一段 JavaScript 代码来与 Deepseek 对话,并回答我们的问题。新建一个文件,ollama.js并粘贴以下内容:

const converter = new showdown.Converter()

async function run(){
    let prompt = document.querySelector("#question").value

    const response = await fetch("http://localhost:11434/api/generate", {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            model: "deepseek-r1:7b",
            prompt: prompt,
            stream: true
        })
    })

    const reader = response.body.getReader()
    const decoder = new TextDecoder()

    let compiledResponse = ""
    while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        const chunk = decoder.decode(value, { stream: true });
        let chunkJson = JSON.parse(chunk)
        compiledResponse += chunkJson.response
        compiledResponse = compiledResponse.replace("<think>", `<div id="think">`)
        compiledResponse = compiledResponse.replace("</think>", `</div>`)
        document.querySelector("#answer").innerHTML = converter.makeHtml(compiledResponse)
    }
}
Enter fullscreen mode Exit fullscreen mode

🤔这里发生了什么?

  • 我们正在创建一个名为的 Javascript 函数run()
  • 在函数中,我们将从 HTML 中的文本框中获取文本document.querySelector("#question").value并将其存储在名为的变量中prompt
  • 然后,我们将使用内置fetch()函数发送包含提示符的POST请求。响应存储在名为 的变量中。由于我们设置了,因此我们将以小块的形式收到响应。http://localhost:11434/api/generateresponsestream: true
  • 为了单独获取每个块,我们将运行response.body.getReader()以获取读取器并TextDecoder使用初始化一个新的new TextDecoder()
  • 我们引入了一个新的空字符串let entireResponse = "",并将其附加到响应的每个块中。
  • 最后,while循环将一直运行,直到所有数据块都处理完毕。对于每个数据块,我们将获取响应,将其添加到entireResponse,进行处理,然后使用 将其显示在网页上document.querySelector("#answer").innerHTML = entireResponseAsHtml

🤔 我们为什么要处理响应?

Deepseek 返回的响应如下所示:

<think>
The user says hello so I should say hello back
</think>

**Hello! How are you doing?**
Enter fullscreen mode Exit fullscreen mode

当我们处理文件时,我们将 替换<think><div id="think">,并将</think>替换为</div>。这样,我们就可以按照自己喜欢的方式设置样式。

entireResponse = entireResponse.replace("<think>", `<div id="think">`)
entireResponse = entireResponse.replace("</think>", `</div>`)
Enter fullscreen mode Exit fullscreen mode

然后,我们还使用 ShowdownJS 库将整个响应从 Markdown 转换为 HTML:

let entireResponseAsHtml = converter.makeHtml(entireResponse)
Enter fullscreen mode Exit fullscreen mode

进口摊牌

最后,我们需要将 ShowdownJS 添加到我们的项目中。只需下载此文件并将其添加到web项目目录中即可。

完成所有这些后,web目录应如下所示:

📝 index.html
📝 ollama.js
📝 showdown.min.js
📝 style.css

步骤 5:将网页添加到 Docker Compose

完成网站创建后,请将您的应用添加到 Docker Compose 文件中,如下所示:

  web:
    image: nginx:1.27.3-alpine
    volumes:
    - ./web:/usr/share/nginx/html
    ports:
    - "3001:80"
Enter fullscreen mode Exit fullscreen mode

您的整个docker-compose.yml文件应如下所示:

services:
  ollama:
    image: ollama/ollama
    volumes:
      - ./ollama-models:/root/.ollama
    ports:
      - 11434:11434

  web:
    image: nginx:1.27.3-alpine
    volumes:
    - ./web:/usr/share/nginx/html
    ports:
    - "3001:80"
Enter fullscreen mode Exit fullscreen mode

运行网站

现在我们已经创建了我们的网站并添加到我们的docker-compose.yml文件中,我们可以使用以下命令运行它:

docker compose up -d web
Enter fullscreen mode Exit fullscreen mode

等待一到两秒钟,然后将浏览器指向此 URL:

http://localhost:3001

如果你看到这个,我们就可以开始了:

网站截图

让我们测试一下!

让我们试试我们的 AI 应用吧!在文本框中写下一个问题,然后点击“提问”按钮。

Deepseek 应该很快就会开始响应了。首先,我们需要“思考”一下……

思考盒

答案框

视频上看起来是这样的:

就这样!现在你只需使用 Docker 就可以在本地运行 Deepseek 了!

现在,每次您想要运行 AI 应用程序时,只需从终端中的项目目录运行此命令:

docker compose up -d
Enter fullscreen mode Exit fullscreen mode

就是这样!

有任何问题?欢迎在这里留言!

文章来源:https://dev.to/savvasstephnds/run-deepseek-locally-using-docker-2pdm
PREV
自动完成的问题及其解决方法
NEXT
想要构建响应式网站?先从移动端开始!