1. 项目概述:构建一个全栈AI代码助手私有化部署方案

最近在折腾一个挺有意思的项目,想把自己用的AI代码助手Claude Code给私有化部署起来。你可能也用过Claude,Anthropic家的那个AI助手,他们的Claude Code专门针对编程场景做了优化,写代码、调试、重构都挺顺手。但直接用他们的在线服务,有时候网络不稳定,数据隐私也是个顾虑,特别是公司内部的一些代码,总不想全传到云端去。

这个项目的核心思路很清晰:用Docker Compose把整个技术栈打包起来,让你能在自己的服务器上快速搭建一个完整的Claude Code环境。它不只是简单地把Claude Code跑起来,而是构建了一个完整的“全栈”方案——前端有CloudCLI UI提供Web界面,后端用Ollama来运行本地的大语言模型,再用Nginx做反向代理统一入口,还能用Certbot自动申请和管理SSL证书。整套东西用Docker容器化,部署起来就像搭积木一样简单。

我实际跑下来发现,这个方案特别适合这几类人:一是开发者个人,想在本地有个稳定的AI编程伙伴;二是小团队,需要内部共享一个代码助手但又不希望数据外流;三是那些对网络环境有特殊要求的场景,比如在内网开发或者网络访问受限的环境。如果你手头有一台Linux服务器(甚至是一台配置不错的个人电脑),16GB以上内存,按照这个方案一两个小时就能搭起来一个完全受你控制的AI编程环境。

2. 技术栈深度解析:为什么选择这套组合拳?

2.1 Claude Code与Ollama的协同工作原理

很多人可能对Claude Code和Ollama的关系不太清楚,这里我详细拆解一下。Claude Code本身是Anthropic提供的AI编程助手,但它需要后端有一个大语言模型来实际处理请求。在云端方案中,这个后端就是Anthropic自己的服务器。但在私有化部署时,我们就需要找一个替代品——这就是Ollama出场的时候。

Ollama本质上是一个本地大模型运行框架,它让你能在自己的机器上拉取和运行各种开源模型,比如Llama、Qwen、Mistral这些。当你在CloudCLI UI(也就是Claude Code的Web界面)里输入一段代码问题,这个请求会通过Nginx代理转发到后端的Ollama容器,Ollama调用你事先加载好的模型来生成回答,再原路返回给前端界面。整个过程中,你的代码和数据完全不会离开你的服务器。

我选择这个方案而不是直接部署某个单一模型,主要考虑了几个实际因素。首先,Ollama支持模型热切换,你今天想用Qwen 2.5,明天想试试Llama 3.2,只需要在Ollama里 pull 一下新模型就行,前端界面完全不用动。其次,Ollama对硬件资源的利用比较高效,它会根据你的GPU/CPU情况自动优化推理,比你自己去折腾PyTorch或Transformers要省心得多。最后,这个生态正在快速成熟,新的模型和优化不断加入,可扩展性很好。

2.2 Nginx反向代理在架构中的关键作用

你可能觉得:“不就是个AI工具吗,直接跑个服务不就行了,干嘛还要加个Nginx?” 这里面的门道我踩过坑才明白。首先,这个项目里实际上跑着三个服务:CloudCLI UI(通常是3000端口)、Ollama(11434端口),还有可选的Portainer(9001端口)。如果没有一个统一的入口,你就得记三个不同的端口和地址,管理起来很麻烦。

Nginx在这里扮演了“交通警察”的角色。所有外部请求都统一到443(HTTPS)或80(HTTP)端口,然后Nginx根据请求的路径智能分发:访问 / 的请求转发到CloudCLI UI,访问 /api 相关的(Claude Code的后端API)也转发过去,而专门给模型推理的请求则转发到Ollama。这样做有几个实实在在的好处:

第一是安全性。Nginx可以统一处理SSL/TLS加密,你只需要在Nginx配置里管理证书,不用每个服务都去折腾HTTPS。第二是负载管理,虽然个人使用可能并发不高,但如果你团队几个人同时用,Nginx能帮你缓冲请求,避免某个服务被突发流量打垮。第三是灵活性,以后你想加个监控面板、日志系统或者别的工具,只需要在Nginx配置里加几行路由规则,不用动现有的服务。

我特别欣赏这个项目里的Nginx配置设计,它在 ./proxy/templates/proxy.conf.template 里用了模板化的方式。这意味着你可以根据自己的网络环境定制配置,比如内网部署可以简化一些安全策略,公网部署则可以加强限流和防护。这种设计比硬编码的配置要灵活得多。

2.3 Docker Compose带来的部署革命

早些年我部署这种多服务应用,得一个个手动安装、配置、启动,光是环境依赖就能折腾一整天。Docker Compose彻底改变了这个局面。这个项目的 docker-compose.yml 文件,你可以理解为一份“食谱”,里面详细定义了每个服务需要什么镜像、挂载哪些目录、开放哪些端口、依赖哪些其他服务。

让我举个例子说明它的威力。这个项目要跑起来,需要:1)一个基于Node.js的CloudCLI UI容器,2)一个Ollama容器来运行模型,3)一个Nginx容器做代理,4)一个Certbot容器管理证书,5)可选的Portainer容器做图形化管理。如果手动部署,你得分别处理五个服务的安装、配置、启动顺序和网络互通。而用Docker Compose,你只需要准备好 .env 配置文件,然后一句 docker compose up -d ,所有服务按正确的顺序自动启动,网络自动打通,卷挂载自动完成。

更重要的是可重现性。你今天在Ubuntu 22.04上搭好了,把整个项目文件夹(包括 docker-compose.yml .env )打包,明天拿到另一台CentOS服务器上,同样的命令就能得到一模一样的环境。这对团队协作和项目迁移来说简直是神器。我团队里现在有新成员加入,我不再需要花半天时间帮他配环境,直接给这个项目仓库地址,他半小时就能跑起来一个可用的开发环境。

3. 硬件与系统准备:避开那些看不见的坑

3.1 硬件配置的理性选择

官方文档说最小16GB RAM,8核CPU,20GB存储。但根据我的实测经验,这个“最小”配置真的只能跑起来,想用得舒服还得加码。我最初在一台16GB内存的机器上试,拉了个7B参数的模型,跑起来后系统就剩2-3GB可用内存了,稍微开几个浏览器标签都卡。后来换到32GB的机器,体验直接上了一个台阶。

这里有个关键点很多人忽略:内存不是只给Ollama用的。Linux系统本身要占1-2GB,Docker引擎要占几百MB,Nginx、CloudCLI UI这些服务每个都要几百MB。更重要的是,当你运行模型时,Ollama会把整个模型加载到内存里进行推理。一个7B的模型,在FP16精度下大概需要14GB内存,在8-bit量化下也要7-8GB。如果你还想同时跑别的服务,或者处理稍长的代码上下文,16GB真的捉襟见肘。

我的建议是:个人学习用途,32GB内存是甜点配置;小团队(3-5人)共享,最好有64GB;如果有GPU,那体验会更好。说到GPU,这里有个细节:Ollama支持NVIDIA GPU加速,但需要安装NVIDIA Container Toolkit。如果你的服务器有RTX 3060(12GB显存)或更好的卡,模型推理速度能快3-5倍。不过没有GPU也能用,CPU推理只是慢一些,对于代码生成这种不需要实时响应的场景,完全可接受。

存储方面,20GB是最低要求,但我建议至少预留50GB。为什么呢?Ollama的模型是下载到本地的,一个Llama 3.2 70B的模型就要40多GB。而且Docker镜像本身、日志文件、证书等都会占用空间。我习惯给 /var/lib/docker 单独挂载一个大容量SSD,因为频繁的容器读写对磁盘IO要求比较高,机械硬盘在这里会成为瓶颈。

3.2 操作系统与依赖的兼容性实战

这个项目支持几乎所有主流Linux发行版,但不同系统下的细微差别我踩过不少坑。先说结论:如果你是从零开始选系统,我推荐Ubuntu 22.04 LTS或Debian 11/12。这两个系统的Docker支持最成熟,社区资源最丰富,遇到问题容易找到解决方案。

我在Alpine Linux上部署时遇到了一个典型问题:Alpine用的是musl libc而不是glibc,有些预编译的二进制包不兼容。虽然项目作者说兼容,但我实际测试时发现Ollama的某些版本在Alpine上需要额外安装兼容库。如果你非要用Alpine,记得安装 libc6-compat 包。Fedora和CentOS系列则要注意SELinux,默认的强制模式可能会阻止Docker挂载卷,要么配置SELinux策略,要么(不推荐生产环境)临时禁用。

Docker和Docker Compose的安装是第一个门槛。这里我分享一个验证安装是否成功的小技巧:装完后不要急着跑项目,先运行 docker run hello-world docker compose version 。如果hello-world能正常输出欢迎信息,compose能显示版本号,说明基础环境OK。如果报权限错误,记得把当前用户加入docker组: sudo usermod -aG docker $USER ,然后 重新登录 终端才会生效——很多人改了不重新登录,然后纠结为什么还是没权限。

还有一个容易忽略的点:时间同步。Docker容器默认用UTC时间,但你的应用日志、证书更新等可能需要本地时间。项目里通过 LOCAL_TIMEZONE 环境变量来解决,比如设成 Asia/Shanghai 。但要注意,有些老系统可能没有安装 tzdata 包,导致时区设置失败。一个检查方法是:在宿主机上运行 timedatectl ,确认时区正确;然后在容器里跑 date ,看是否一致。

4. 从零开始的部署实战:手把手带你走通全流程

4.1 环境配置与项目初始化

拿到这个项目,第一步不是直接运行安装脚本,而是先理解整个目录结构。我建议先用 git clone 拉取代码,然后花几分钟看看里面有什么:

git clone https://github.com/damalis/full-stack-proxy-nginx-claude-code-for-everyone-with-docker-compose.git
cd full-stack-proxy-nginx-claude-code-for-everyone-with-docker-compose
ls -la

你会看到几个关键文件: docker-compose.yml 是主配置文件, docker-compose-portainer.yml 是Portainer的配置, .env.example 是环境变量模板, install.sh 是自动化安装脚本,还有 proxy/ 目录存放Nginx配置模板。

我个人的习惯是先手动配置一遍,理解每个环节,然后再考虑用自动化脚本。所以这里我们先走手动流程。复制环境变量模板:

cp .env.example .env

现在用编辑器打开 .env 文件,你会看到这几个关键变量需要配置:

  • LOCAL_TIMEZONE :你的时区,比如 Asia/Shanghai 。获取完整列表可以查维基百科的时区数据库页面,或者直接在Linux下运行 timedatectl list-timezones | grep -i shanghai
  • DOMAIN_NAME :这是最重要的配置之一。如果你只是本地测试,可以用 localhost 。但如果你想通过域名访问(比如团队内网共享),这里要填你的域名,比如 yourcompany.com 。注意:后面访问地址会是 https://claude.yourcompany.com
  • DIRECTORY_PATH :项目根目录的绝对路径。最简单的办法就是在项目目录下运行 pwd ,把输出复制到这里。
  • LETSENCRYPT_EMAIL :申请Let's Encrypt证书用的邮箱。如果只是本地测试,可以随便填一个邮箱,但格式要对,比如 test@example.com
  • SSL_SNIPPET :SSL证书生成策略。本地测试选 localhost ,会生成自签名证书;公网部署选 remotehost ,会自动申请Let's Encrypt证书。
  • ANTHROPIC_API_KEY :如果你有Claude官方的API密钥,可以填在这里,这样Claude Code可以回退到官方API(当本地模型不可用时)。如果没有或者想完全本地运行,留空即可。

这里有个重要细节:如果你用域名部署, 必须提前配置好DNS 。也就是说,你要把 claude.yourdomain.com 这个子域名解析到你的服务器IP。很多人在这一步卡住,证书申请失败就是因为DNS没生效。怎么检查?在配置前,先在别的电脑上 ping claude.yourdomain.com ,看是否能解析到正确IP。

4.2 证书管理的两种策略与选择

SSL证书是HTTPS的基础,这个项目提供了两种完全不同的证书策略,适应不同场景。

本地自签名证书方案 :适合纯内网测试或开发环境。当你设置 SSL_SNIPPET=localhost 时,项目会使用 mkcert 工具生成自签名证书。这种证书浏览器会显示“不安全”警告,你需要手动点击“高级”->“继续前往”才能访问。它的好处是完全离线可用,不用依赖任何外部服务,也不用暴露服务器到公网。我一般在初次验证部署流程时用这个模式,快速测试所有服务是否能正常启动。

Let's Encrypt自动证书方案 :适合公网或内网正式使用。设置 SSL_SNIPPET=remotehost 并配置正确的域名和邮箱后,Certbot容器会自动通过ACME协议向Let's Encrypt申请免费证书。这里的工作原理是:Certbot会启动一个临时Web服务在80端口,Let's Encrypt的验证服务器访问你的域名,确认你控制这个域名后签发证书。证书有效期90天,但Certbot会自动续期。

我强烈建议即使在内网也尽量用Let's Encrypt证书,除非你的内网完全隔离。因为现代浏览器对自签名证书越来越不友好,有些新的Web API(比如某些PWA功能)在自签名证书下根本不能用。而且团队成员每次访问都要点“继续前往”,体验很差。

证书申请常见问题排查:如果证书申请失败,首先检查80端口是否开放(Let's Encrypt验证需要),然后检查DNS解析是否正确,最后检查防火墙是否放行了80和443端口。一个快速测试方法是:在服务器上运行 sudo nc -l 80 ,然后在另一台机器上 telnet 你的域名 80 ,看是否能连接。

4.3 服务启动与初次访问验证

环境变量配置好后,就可以启动服务了。先创建证书存储的Docker卷:

docker volume create --driver local --opt type=none --opt device=${PWD}/certbot --opt o=bind certbot-etc

这个命令创建了一个持久化卷,把宿主机的 ./certbot 目录挂载到容器的证书存储位置。这样即使容器重建,证书也不会丢失。注意 ${PWD} 会自动展开为当前目录,确保你在项目根目录下执行。

现在启动所有服务:

docker compose up -d

-d 参数表示后台运行。第一次运行会下载所有Docker镜像,根据网络情况可能需要5-15分钟。你可以用 docker compose logs -f 实时查看日志,确认各个服务启动是否正常。

看到所有容器都显示 done 后,需要重启一下Nginx代理,让它加载新的SSL配置:

docker container restart proxy

现在打开浏览器,访问 https://claude.yourdomain.com (本地测试用 https://localhost )。如果一切正常,你会看到CloudCLI UI的安装页面。如果看到证书警告(本地自签名证书),按照浏览器提示接受风险继续访问。

重要提示 :第一次访问可能会比较慢,因为Ollama在初始化。如果页面长时间加载,可以查看日志: docker compose logs ollama ,看模型是否在下载或加载。

Portainer的启动是可选的,但它对于不熟悉Docker命令的团队成员来说是个很好的管理工具:

docker compose -f portainer-docker-compose.yml -p portainer up -d

启动后访问 https://claude.yourdomain.com:9001 ,首次访问需要设置管理员密码,然后就能看到所有容器的图形化界面了。

5. 模型管理与优化:让AI真正理解你的代码

5.1 模型选择与下载策略

服务跑起来只是第一步,真正决定体验的是你选择的模型。Ollama支持几十种开源模型,但不是所有都适合代码生成。根据我的实测经验,以下几个模型在代码任务上表现突出:

Qwen 2.5系列 :这是我目前的主力推荐,特别是Qwen 2.5 Coder系列。7B版本在16GB内存上就能流畅运行,32B版本质量更高但需要更大内存。它的代码生成质量接近GPT-4,对中文支持也很好,而且指令跟随能力强。下载命令: docker exec -it ollama ollama pull qwen2.5-coder:7b

Llama 3.2系列 :Meta的最新力作,3B版本就能有不错的代码能力,适合资源有限的场景。11B版本是甜点,70B版本质量最高但需要大量资源。Llama系的优势是生态丰富,很多工具和优化都优先支持。下载: docker exec -it ollama ollama pull llama3.2:11b

CodeLlama系列 :专门为代码训练的模型,在代码补全、调试、解释方面有专长。但注意它可能在其他非代码任务上表现一般。下载: docker exec -it ollama ollama pull codellama:13b

DeepSeek Coder :国产模型中代码能力很强的选手,对中文代码注释生成特别友好。下载: docker exec -it ollama ollama pull deepseek-coder:6.7b

我建议的下载策略是:先拉一个小模型(如Qwen 2.5 Coder 7B或Llama 3.2 3B)快速验证,确认整个流程没问题。然后根据你的硬件条件,选择一个“主力模型”。如果内存充足(32GB+),可以上13B-34B参数的模型;如果只有16GB,7B模型是更安全的选择。

下载模型时有个技巧:Ollama默认会下载适合你系统的最佳版本(比如有GPU就下GPU优化版)。但你可以指定版本,比如 qwen2.5-coder:7b-q4_K_M ,这里的 q4_K_M 是量化等级,影响模型大小和精度。 q4_K_M 是推荐的平衡点, q8_0 精度更高但更大, q2_K 最小但质量损失明显。

5.2 模型加载与内存优化实战

模型下载完后,默认不会自动加载到内存。Ollama采用按需加载策略,当你第一次通过Claude Code发送请求时,它才会加载模型。这个过程可能需要几十秒到几分钟,取决于模型大小和磁盘速度。

你可以手动预加载模型来避免第一次请求的等待:

docker exec -it ollama ollama run qwen2.5-coder:7b "Hello"

这个命令会加载模型并运行一个简单对话,之后模型就会常驻内存。但注意:Ollama同时只能加载一个模型,如果你切换模型,前一个会被卸载。

内存管理是模型运行的关键。Ollama有几个重要的环境变量可以调整,这些可以在 docker-compose.yml 的ollama服务部分配置:

  • OLLAMA_NUM_PARALLEL :并行处理数,默认是CPU核心数。如果你的CPU很强但内存有限,可以调低这个值减少内存压力。
  • OLLAMA_HOST :监听地址,默认 0.0.0.0:11434 ,不要改除非有特殊网络需求。
  • OLLAMA_KEEP_ALIVE :模型在内存中的保持时间,默认5分钟。如果你内存充足,可以设为 -1 让模型常驻;如果内存紧张,可以缩短这个时间。

对于GPU用户,需要在宿主机安装NVIDIA Container Toolkit,然后在 docker-compose.yml 中为ollama服务添加GPU支持:

services:
  ollama:
    # ... 其他配置
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

安装NVIDIA Container Toolkit的步骤:先安装NVIDIA驱动,然后添加Docker的NVIDIA运行时。不同Linux发行版命令不同,以Ubuntu为例:

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker

安装后运行 docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi ,如果能看到GPU信息,说明配置成功。

5.3 Claude Code界面配置与使用技巧

第一次访问CloudCLI UI,你需要进行一些基本配置。界面通常很直观,但有几个关键设置影响使用体验:

模型选择 :在设置中找到“Model”或“后端”选项,这里应该能看到Ollama。选择后,下面会列出Ollama中已下载的模型。如果没看到模型列表,检查:1)Ollama容器是否正常运行( docker ps | grep ollama ),2)网络是否连通(在CloudCLI UI容器内 curl http://ollama:11434/api/tags )。

上下文长度 :代码生成通常需要较长上下文。在模型配置中,把上下文长度(context length)调到模型支持的最大值,比如Qwen 2.5 Coder 7B支持32K tokens。但注意:更长的上下文消耗更多内存,如果处理大文件时内存不足,可以适当调低。

温度(Temperature) :控制生成随机性。写代码时我通常设为0.2-0.3,这样生成结果更确定、更可靠。如果你想要更多创意方案,可以调到0.7左右。

系统提示词 :这是提升代码生成质量的关键。Claude Code允许你设置系统级提示词,比如:“你是一个专业的Python开发助手,遵循PEP 8规范,代码要有详细注释,优先使用标准库。”这样的提示词能让模型更符合你的编码风格。

实际使用中,我发现几个高效技巧:第一,给模型明确的文件上下文。在提问前,先把相关代码文件的内容贴进去,模型才能给出针对性建议。第二,分解复杂任务。不要一次让模型写整个项目,而是分模块、分函数地请求。第三,利用好“修复”功能。当模型生成的代码有bug时,把错误信息贴回去让它修复,这比从头开始描述问题更高效。

6. 网络与安全配置进阶

6.1 Nginx反向代理的深度定制

项目自带的Nginx配置已经能处理大部分场景,但实际部署时你可能需要一些定制。所有Nginx配置都在 ./proxy/templates/proxy.conf.template ,这是一个Jinja2模板,实际生成的配置文件在 ./proxy/nginx.conf

基本路由理解 :模板里定义了三个主要的 location 块:

  • location / 处理前端静态文件和API请求,代理到CloudCLI UI( cloudcli 服务)
  • location /api/ 专门处理Claude Code的后端API
  • location /ollama/ 将Ollama的API暴露给前端

如果你需要添加新的服务,比如想集成一个代码仓库浏览器,可以添加新的 location 块:

location /git/ {
    proxy_pass http://gitea:3000/;  # 假设你有个Gitea服务
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

性能调优参数 :默认配置适合大多数情况,但高并发时可能需要调整。以下几个参数我经常修改:

# 增加缓冲区大小,处理大请求(如长代码文件)
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;

# 增加超时时间,模型推理可能较慢
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;

# 启用gzip压缩,减少传输数据量
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

安全加固 :生产环境部署时,建议添加一些安全头:

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

修改配置后,需要重启Nginx容器: docker container restart proxy 。或者更优雅的方式: docker exec proxy nginx -s reload ,这样不会中断现有连接。

6.2 防火墙与访问控制策略

即使在内网,良好的访问控制也是必要的。我建议至少做三层防护:

第一层:系统防火墙 。只开放必要的端口。对于这个项目,需要:

  • 80/tcp:HTTP,用于证书申请验证(Let's Encrypt)
  • 443/tcp:HTTPS,主要服务端口
  • 9001/tcp:Portainer管理界面(可选)

如果你用UFW(Ubuntu默认),命令如下:

sudo ufw allow 80/tcp comment 'HTTP for certbot'
sudo ufw allow 443/tcp comment 'HTTPS for services'
sudo ufw allow 9001/tcp comment 'Portainer UI'
sudo ufw enable

如果是firewalld(CentOS/RHEL):

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

第二层:Nginx访问限制 。可以在Nginx配置中添加IP白名单。比如只允许公司内网IP访问:

location / {
    allow 192.168.1.0/24;  # 内网网段
    allow 10.0.0.0/8;       # 另一个内网网段
    deny all;
    
    proxy_pass http://cloudcli:3000;
    # ... 其他代理设置
}

或者添加基础认证:

location / {
    auth_basic "Restricted Access";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    proxy_pass http://cloudcli:3000;
}

然后在容器内创建密码文件: docker exec -it proxy sh -c "echo -n 'username:' >> /etc/nginx/.htpasswd && openssl passwd -apr1 >> /etc/nginx/.htpasswd" ,输入密码即可。

第三层:应用层认证 。CloudCLI UI本身可能支持用户认证,或者你可以在前面再加一层认证代理(如Authelia)。对于小团队,我通常用Nginx基础认证就够了。

6.3 域名与DNS配置实战

如果你用域名访问,正确配置DNS是关键。这里分几种情况:

公有云服务器+自有域名 :这是最标准的场景。假设你的域名是 example.com ,服务器公网IP是 1.2.3.4

  1. 在域名注册商的控制台添加A记录: claude.example.com -> 1.2.3.4
  2. 等待DNS传播(通常几分钟到几小时)
  3. 在服务器防火墙开放80和443端口
  4. 配置 .env 中的 DOMAIN_NAME example.com
  5. 启动服务,Certbot会自动申请证书

内网服务器+本地DNS :很多公司内网有本地DNS服务器。假设内网域是 company.local ,服务器内网IP是 192.168.1.100

  1. 在内网DNS添加A记录: claude.company.local -> 192.168.1.100
  2. 或者更简单:在所有客户端修改 /etc/hosts (Linux/Mac)或 C:\Windows\System32\drivers\etc\hosts (Windows),添加一行: 192.168.1.100 claude.company.local
  3. 可以用自签名证书,或者在内网部署一个私有CA

动态IP或没有固定域名 :可以用DDNS服务,或者用 nip.io 这样的神奇域名。比如你的IP是 1.2.3.4 ,可以直接用 claude.1.2.3.4.nip.io 作为域名,它会自动解析到 1.2.3.4 。但注意Let's Encrypt可能对这类域名有频率限制。

DNS配置后如何验证?几个有用的命令:

  • dig claude.yourdomain.com nslookup claude.yourdomain.com :查看DNS解析结果
  • curl -I http://claude.yourdomain.com :测试HTTP访问(80端口)
  • openssl s_client -connect claude.yourdomain.com:443 -servername claude.yourdomain.com :测试HTTPS和证书

如果证书申请失败,查看Certbot日志: docker compose logs certbot 。常见错误包括:DNS未生效、80端口被占用、防火墙阻止访问、Let's Encrypt速率限制(同一域名每周最多5次申请失败)。

7. 运维与故障排查手册

7.1 日常运维命令速查

这个项目跑起来后,日常维护主要靠几个Docker命令。我整理了一个速查表:

任务 命令 说明
查看所有容器状态 docker compose ps 简洁状态,或 docker ps -a 看全部
查看实时日志 docker compose logs -f 所有服务日志, -f 跟随输出
查看单个服务日志 docker compose logs -f ollama 只看Ollama日志
重启单个服务 docker compose restart ollama 不重启其他服务
重启所有服务 docker compose restart 优雅重启
停止所有服务 docker compose stop 停止但不删除
启动已停止服务 docker compose start 启动之前停止的服务
彻底停止并清理 docker compose down 停止并删除容器、网络
彻底清理(含卷) docker compose down -v 小心!会删除证书等数据
进入容器shell docker exec -it ollama sh 调试容器内部
更新镜像并重启 docker compose pull && docker compose up -d 更新到最新镜像

日志分析技巧 :当服务异常时,按这个顺序排查:

  1. docker compose logs --tail=50 :看最近50行日志,快速了解错误
  2. docker compose logs service_name > service.log :把某个服务日志导出到文件,方便搜索
  3. 关注常见错误关键词: error failed panic timeout connection refused

资源监控 :定期检查资源使用情况:

  • docker stats :实时查看所有容器CPU、内存、网络使用
  • df -h :查看磁盘空间,特别是 /var/lib/docker 所在分区
  • free -h :查看内存使用,确保有足够可用内存给模型

7.2 常见问题与解决方案

我在部署和维护过程中遇到过各种问题,这里总结最常见的几个:

问题1:容器启动失败,端口被占用

Error starting userland proxy: listen tcp4 0.0.0.0:443: bind: address already in use

解决 :查找占用端口的进程: sudo lsof -i :443 sudo netstat -tlnp | grep :443 ,然后停止那个进程,或者修改 docker-compose.yml 中的端口映射,比如把 443:443 改为 8443:443 ,然后通过8443端口访问。

问题2:证书申请失败

Certbot failed to authenticate some domains

解决 :首先确认域名解析正确: ping claude.yourdomain.com 。然后检查80端口是否开放且能被公网访问:在服务器上 sudo nc -l 80 ,在另一台公网机器 telnet yourdomain.com 80 。如果公司防火墙阻止80端口,可以考虑用DNS验证方式,但需要修改Certbot配置。

问题3:Ollama模型下载慢或失败

Error: failed to pull model: Get "https://ollama.com/...": dial tcp: lookup ollama.com on 127.0.0.53:53: read udp 127.0.0.1:12345->127.0.0.53:53: i/o timeout

解决 :这是网络问题。可以尝试:1)使用镜像源,但Ollama官方镜像不多;2)手动下载模型文件,然后导入:先在其他网络好的机器下载,用 ollama pull ,然后 ollama show --modelfile 导出Modelfile,再在目标机器创建;3)设置HTTP代理:在 docker-compose.yml 的ollama服务添加环境变量 HTTP_PROXY HTTPS_PROXY

问题4:Claude Code界面无法连接Ollama

Failed to connect to Ollama: Connection refused

解决 :检查几个点:1)Ollama容器是否运行: docker ps | grep ollama ;2)网络是否互通:在CloudCLI UI容器内执行 curl http://ollama:11434/api/tags ;3)Ollama服务是否正常: docker exec ollama ollama list ;4)查看Ollama日志: docker compose logs ollama | tail -50

问题5:内存不足,容器被OOM杀死

Killed process ... (ollama) total-vm:32675348kB, anon-rss:28954372kB, file-rss:0kB, shmem-rss:0kB

解决 :这是最常见的问题。解决方案:1)换更小的模型;2)增加系统内存;3)调整Ollama参数:在 docker-compose.yml 中为ollama服务添加内存限制,并设置OOM优先级;4)使用模型量化版本(如q4_K_M而不是q8_0);5)确保没有其他程序占用大量内存。

问题6:磁盘空间不足

no space left on device

解决 :Docker很占磁盘空间。清理方法:1) docker system prune -a :清理所有未使用的镜像、容器、网络;2) docker volume prune :清理未使用的卷;3)删除旧的模型: docker exec ollama ollama rm 模型名 ;4)定期清理日志:配置Docker日志轮转。

7.3 备份与恢复策略

这个项目的数据主要在三处:1)Docker卷中的证书,2)Ollama中的模型,3)可能的用户数据(如果Claude Code有持久化存储)。

证书备份 :证书在 certbot-etc 卷中,实际映射到宿主机的 ./certbot 目录。最简单的备份就是复制这个目录:

cp -r ./certbot ./certbot_backup_$(date +%Y%m%d)

恢复时,停止服务,用备份覆盖原目录,重启服务。

模型备份 :Ollama的模型默认在容器内,但可以通过卷持久化。修改 docker-compose.yml

services:
  ollama:
    volumes:
      - ollama_models:/root/.ollama
volumes:
  ollama_models:

这样模型就保存在Docker卷 ollama_models 中。备份卷: docker run --rm -v ollama_models:/data -v $(pwd):/backup alpine tar czf /backup/ollama_backup.tar.gz -C /data . 。恢复时创建新卷并解压。

完整项目备份 :最简单的完整备份就是备份整个项目目录:

tar czf claude_code_backup_$(date +%Y%m%d).tar.gz \
  --exclude=./certbot/conf/live/*/privkey.pem \  # 排除私钥,安全考虑
  --exclude=./certbot/conf/archive \
  --exclude=./.env \  # 环境变量单独备份
  .

恢复时:解压到新目录,恢复 .env 文件,运行 docker compose up -d

自动化备份脚本 :我写了一个简单的备份脚本,放在 cron 中每天运行:

#!/bin/bash
BACKUP_DIR="/backup/claude_code"
DATE=$(date +%Y%m%d)

# 备份证书
tar czf $BACKUP_DIR/certbot_$DATE.tar.gz -C ./certbot .

# 备份docker-compose文件
cp docker-compose.yml $BACKUP_DIR/docker-compose_$DATE.yml
cp .env $BACKUP_DIR/env_$DATE

# 备份模型(如果有持久化卷)
docker run --rm -v ollama_models:/data -v $BACKUP_DIR:/backup alpine \
  tar czf /backup/ollama_models_$DATE.tar.gz -C /data .

# 删除7天前的备份
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete
find $BACKUP_DIR -name "*.yml" -mtime +7 -delete

7.4 性能监控与优化建议

长期运行后,你可能需要监控服务性能并做优化。几个关键监控点:

内存使用 :Ollama是内存大户。监控命令: docker stats ollama 。如果内存使用持续接近限制,考虑:1)换更小的模型,2)调整Ollama的 OLLAMA_NUM_PARALLEL 减少并行数,3)增加swap空间(临时方案)。

响应时间 :在Claude Code界面感受响应速度,如果变慢,检查:1)模型是否太大,2)CPU是否过载,3)网络延迟。可以用 docker exec ollama ollama run model_name "1+1" 测试纯模型响应时间。

存储空间 :定期检查Docker磁盘使用: docker system df 。重点关注镜像和卷的使用。模型更新时会下载新镜像,旧镜像不会自动删除。

网络流量 :如果多人使用,监控网络带宽。Nginx访问日志在 ./proxy/logs/ ,可以分析访问模式。

优化建议

  1. 模型选择优化 :根据实际使用场景选择模型。纯代码生成可以用专门的代码模型(如CodeLlama),综合任务用通用模型(如Qwen 2.5)。
  2. 硬件优化 :如果有GPU,确保NVIDIA驱动和容器工具包正确安装。没有GPU但CPU较强,可以尝试使用支持CPU优化的模型版本。
  3. 服务分离 :如果资源充足,可以把Ollama和CloudCLI UI分开部署在不同服务器,通过内网连接,减轻单机压力。
  4. 缓存策略 :Nginx可以配置缓存,对静态资源和某些API响应进行缓存,减少后端压力。
  5. 定期更新 :每月检查一次镜像更新: docker compose pull ,然后 docker compose up -d 重启服务。注意:更新前备份 .env 和重要数据。

这套全栈Claude Code部署方案,我从最初的好奇尝试,到现在的生产环境稳定运行,已经用了小半年时间。最大的体会是:私有化部署AI工具不再是大型企业的专利,个人开发者和小团队完全有能力搭建和维护自己的AI基础设施。关键是要理解每个组件的作用,知道出了问题该从哪里查起。这个项目提供的Docker Compose方案,把复杂的系统集成工作简化到了几个配置文件和命令,让更多人能够享受到本地AI助手的便利。

实际使用中,我发现最影响体验的不是技术问题,而是使用习惯的调整。刚开始总想着让AI写完整的功能,后来发现让它帮忙写单元测试、写文档、重构代码片段、解释复杂逻辑,这些才是真正提升效率的地方。还有个小技巧:给AI明确的上下文,比如“这是Django项目的models.py,现在要添加一个用户Profile模型,字段包括avatar、bio、website”,比单纯说“写个用户模型”得到的结果要好得多。

如果团队使用,建议制定一些使用规范:比如哪些代码适合让AI生成,哪些需要人工审核;如何编写有效的提示词;生成代码的版权和合规性考虑。这些非技术问题,有时候比技术部署更重要。

更多推荐