ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Nginx反向代理Tomcat部署实战:从单机到容器化完整指南

Nginx反向代理Tomcat部署实战:从单机到容器化完整指南 我第一次练手Java Web时是直接把Tomcat的8080端口扔给浏览器的后来才明白真实项目里站在用户和Tomcat之间的永远还有一个Nginx。这个“练习-部署nginx和部署tomcat”的完整笔记就是把自己从“能启动一个Tomcat”带到“能像生产环境那样用Nginx负责入口、Tomcat负责Java业务”的整个过程。如果你和我一样已经会用IDEA启动一个Spring Boot工程或者刚学完Servlet但脑子里对“下载nginx之后里面是什么”“location配置到底怎么生效”“静态资源要不要塞进Tomcat”这些事完全没有概念这篇文章应该能帮你把整条链路理顺。内容覆盖Tomcat下载安装与多实例端口改造、IDEA 2026里找不到Tomcat Server的坑、Nginx下载与location工作流机制、多站点自定义域名、并发与日志排查、Docker和K8s部署最后加一个给Ollama加反向代理鉴权的热门玩法。1. 把nginx和tomcat放一起到底练什么1.1 这套组合在生产环境的真实分工先想清楚一个问题为什么生产环境里很少让Tomcat直接面对用户Tomcat是Servlet容器它的本职是跑Java的Web应用处理JSP、Servlet、Spring MVC那一套动态逻辑。但它的静态资源处理能力、抗并发连接能力并不是强项。Nginx恰恰相反它是高性能的Web服务器和反向代理处理静态文件、HTTP连接、负载均衡、SSL终结都非常利索。正常情况下一次请求的链路是这样用户浏览器请求到达Nginx80或443端口 - Nginx判断请求是静态还是动态 - 静态文件css、js、图片由Nginx直接返回 - 动态请求通过proxy_pass转发给后端Tomcat8080端口 - Tomcat处理完返回给Nginx - Nginx再回给用户。这套分工看着简单但它解决了很多实际问题Tomcat不用再纠结静态资源缓存和并发连接可以把线程池全留给业务逻辑Nginx可以同时代理多台Tomcat做到负载均衡在Nginx层还可以统一做HTTPS证书、限流、鉴权。所以“部署nginx和部署tomcat”这个练习练的不是“把两个软件装起来”而是练“一台入口代理 一台业务容器的协作关系”。1.2 练习目标规划从单机到多站点我把这个练习拆成四个阶段每一个阶段都是后面一步的基础单机阶段Tomcat能独立启动并访问Nginx能独立启动并访问。串联阶段Nginx把请求反向代理给Tomcat用户只访问Nginx但页面是Tomcat出来的。扩展阶段在Nginx里配置多个server块用不同端口或不同自定义域名区分站点做到一个Nginx管理多个Tomcat。排错与进阶阶段解决HTTPS证书报错、并发“老是用超”、日志定位、容器化部署以及给大模型服务Ollama加反向代理鉴权。这个练习不需要昂贵的生产服务器一台Windows笔记本、一台Mac或者一台Linux虚拟机就够了。Tomcat和Nginx都是解压即用的软件唯一需要提前装好的依赖就是JDK。2. 先搞定tomcat版本坑、安装步骤、多实例端口改造2.1 版本选择不要见到新版本就上Tomcat的版本选择是第一个坑。很多人一上来就下最新版结果项目跑不起来。Tomcat 10之后有个巨大的变化Java EE的包名从javax.*换成了jakarta.*老项目如果用的还是javax.servlet.*丢进Tomcat 10里直接编译报错。我的建议是如果JDK是8项目是传统的Servlet或Spring MVC直接选Tomcat 8.5系列如果JDK是11或17恰好项目也是新写的用Tomcat 9更稳。Tomcat 10类的版本留给真正做过包名迁移的团队去考虑。版本Servlet规范包名适合场景Tomcat 8.5Servlet 3.1javax.*JDK8老项目最稳Tomcat 9Servlet 4.0javax.*JDK8/JDK11兼容性好Tomcat 10/11Servlet 5.0/6.0jakarta.*新项目或已迁移项目下载地址在tomcat.apache.org找到对应版本的Core下的zip或tar.gz即可。记住不要下src包和deployer包那是源码和打包工具普通部署用不到。2.2 单实例部署与验证安装前先确认一件事有没有配好JAVA_HOME环境变量。Tomcat启动脚本是靠JAVA_HOME去找Java的不是靠PATH。Windows下可以在命令行跑一句echo %JAVA_HOME%Linux下是echo $JAVA_HOME如果输出为空先去安装JDK并配置环境变量。Tomcat解压后目录结构有几个关键点需要认识bin启动脚本Windows下是startup.batLinux下是startup.sh。conf核心配置文件重点是server.xml和web.xml。webapps部署Web应用的地方war包扔进去会自动解压。logs运行日志排错主要看这里。Windows下进入bin目录双击startup.bat会弹出一个命令行窗口并显示Tomcat的启动日志。启动成功后浏览器访问http://localhost:8080看到那只猫的页面就算通了。这里我多说一句很多人会遇到Tomcat启动出现一闪而过的情况也就是双击startup.bat后窗口瞬间关闭。这不是正常现象说明启动失败了。正确排查姿势是打开cmd进入bin目录手动执行catalina.bat run这样错误信息会留在控制台里不会闪退。最常遇到的三个原因一是没配JAVA_HOME二是8080端口被占用比如IDEA里某个服务还开着三是CATALINA_HOME环境变量指错了目录。2.3 多实例部署的三个端口改造练习到后面你会发现一个Tomcat不够用两个项目想同时跑又不想挤在同一个Tomcat里。Tomcat支持多实例做法听起来很粗暴——再复制一份Tomcat目录改几个端口。复制一份之后千万不能直接启动否则肯定报端口冲突。一个Tomcat实例在网络上有三个端口的配置集中在conf/server.xml端口作用默认值8005shutdown关闭命令监听端口80058080HTTP连接器浏览器访问入口80808009AJP 1.3协议连接端口8009修改规则很简单三个端口都要和第一个实例错开。比如第一个实例是8005/8080/8009第二个实例可以改成8006/8081/8010第三个改成8007/8082/8011。为什么要改三个而不是只改8080如果只改8080两个实例的8005端口就冲突了而且8009端口也冲突。万一不小心用shutdown脚本关一个另一个也会被误伤。多实例的正确玩法就是彻底隔离端口。改完之后分别启动访问http://localhost:8081和http://localhost:8082对应不同的实例。2.4 IDEA 2026找不到Tomcat Server的排查与解决这个坑来自一个很热门的搜索词IDEA 2026本地部署Tomcat9没找到Tomcat Server。很多人从官网下了Tomcat想在IDEA的Run Configuration里直接加一个Tomcat Server运行项结果发现找不到这个选项。第一类原因最扎心IDEA的Community社区版根本没有Tomcat内建集成只有Ultimate旗舰版才有。如果你用的是社区版与其找替代方案不如直接装一个官方推荐的Smart Tomcat插件插件市场里搜“Smart Tomcat”安装后重启在Run Configuration里就能看到Smart Tomcat选项配置里指定Tomcat路径和工作目录即可。第二类原因是你确实是旗舰版但忘记先配置应用服务器。正确做法是打开Settings - Build, Execution, Deployment - Application Servers。点加号选择Tomcat Server。在Tomcat Home那一栏填入Tomcat目录路径IDEA会自动识别版本号。确认后在Run Configuration里就有Tomcat Server - Local选项了。第三类原因是新版IDEA对Tomcat的入口做了调整如果你在应用服务器里配好了还是看不到检查IDEA版本升级后插件是否被禁用。另外有一个细节部署时选war包或war exploded时要指定Application context这些都会影响访问路径。3. nginx部署开跑下载启动和location工作流机制3.1 下载与启动Windows和Linux的差异Nginx的官方下载地址是nginx.org打开首页的download链接就能看到版本列表。我们练习就用主线稳定版即可比如1.24或1.26系列。Windows下直接下载nginx-1.x.x.zip解压出来就能用不需要安装。这里顺便回答一个搜索词nginx是不是免费的是它和Tomcat一样免费开源放心用。Nginx目录结构不大核心是这几个conf/nginx.conf主配置文件。html默认静态页面存放目录。logs访问日志和错误日志默认目录。temp运行时临时文件。Windows下的启动方式和Tomcat不太一样。进入解压目录命令行执行start nginx这句会启动一个后台进程。之后要验证状态访问http://localhost看到“Welcome to nginx!”页面就是成功了。注意Nginx默认监听80端口80被占用会导致启动失败最常见的占用者是IIS或另一个Nginx。停止和重载的命令分别是nginx -s stop nginx -s reloadstop是快速停止reload是平滑重载。为什么改配置文件后大家都推荐用reload因为它是主进程读取新配置、重新拉起worker进程已建立的连接不会被中断用户体验上是无感的。这在生产环境里是一个特别重要的习惯。Linux下安装更简单Ubuntu/Debian系跑apt install nginxCentOS/RHEL系跑yum install nginx。作为练习系统包安装足够了。想自己编译安装的话就是从官网拿源码跑./configure --prefix/usr/local/nginx make make install生产环境脚本化部署时更常见。3.2 location匹配规则与优先级Nginx配置里最容易被绕晕的就是location但我可以用一句话先破题location匹配的总体逻辑是“先精确再前缀再正则谁匹配最长用谁”。先看常见配置长什么样location / { proxy_pass http://127.0.0.1:8080; } location / { root html; index index.html; } location ^~ /api/ { proxy_pass http://127.0.0.1:8081; } location ~ \.jsp$ { proxy_pass http://127.0.0.1:8080; }每条规则前面的符号代表了不同的匹配方式表示精确匹配。请求URI必须和路径完全一致才会命中命中后立即使用不再查后面的规则。不带符号的普通前缀匹配。比如location /它匹配所有以/开头的URI。多个普通前缀匹配时采用最长匹配原则比如/api/user会优先匹配/api/而不是/。^~表示前缀匹配但一旦命中就不再查正则。它比普通前缀高一级相当于“我就要这个前缀后面不用折腾了”。~和~*表示正则匹配前者区分大小写后者不区分。正则按配置顺序从上往下执行第一个匹配成功的生效。所以完整的工作流是这样的先找有没有精确匹配有就直接用没有就找最长普通前缀匹配包括^~如果最长前缀是^~开头的直接定案如果最长前缀只是普通前缀还会回头去按顺序跑正则一旦正则匹配成功正则胜出如果正则全部没匹配上才用之前那个最长普通前缀。这个机制必须吃透因为后面所有反向代理、动态静态分流都靠它。举个真实的例子你配置了location /把全部请求转发给Tomcat又配了location ^~ /static/想接静态文件结果因为普通前缀没有^~请求/static/app.js还是被location /转发走了静态资源全部404。这种问题不看规则根本猜不到原因。3.3 动态静态分流核心反代配置模板理解了location机制就可以写一份真正的反代配置。下面这个server块是练习阶段最常用的模板server { listen 80; server_name localhost; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~* \.(css|js|png|jpg|jpeg|gif|ico)$ { root html; expires 7d; } }第一段把动态请求全转发给8080端口的Tomcat。第二段用正则匹配静态文件后缀由Nginx直接从html目录返回不经过Tomcat。expires 7d是让浏览器缓存静态文件7天这是Nginx处理静态资源的一大优势。里面的proxy_set_header很多人会漏写但每个都很关键。Host $host会把原始请求的Host头传给后端Tomcat如果不传Tomcat收到的Host可能是127.0.0.1:8080那样它在生成重定向链接时就会返回一个错误的地址。X-Real-IP和X-Forwarded-For是告诉后端“真实的用户IP是谁”这样应用日志里记的不是Nginx的IP而是访问者的IP。改完配置文件一定先跑一句nginx -t它会检查配置文件语法显示test is successful后再执行nginx -s reload。这个习惯能帮你少踩很多坑。4. 多端口、多站点、自定义域名server块实战4.1 hosts绑定自定义域名本地练习时没有真实域名但我们可以让操作系统“骗”自己用hosts文件把自定义域名指向本机IP。Windows的hosts路径是C:\Windows\System32\drivers\etc\hostsLinux/Mac是/etc/hosts用管理员权限或sudo编辑加两行127.0.0.1 app1.test.local 127.0.0.1 app2.test.local保存后ping一下app1.test.local如果解析到了127.0.0.1就成功。这里不要用localhost本身因为多站点场景下Nginx需要通过server_name匹配域名如果所有站点都用localhost就分不清到底该访问哪一个。一句话解释为什么Nginx能靠域名区分站点用户在浏览器地址栏输入域名后浏览器会把这个域名放在HTTP请求的Host头里发给NginxNginx拿Host和server_name做比对命中哪个server块就进入哪个块。这就是虚拟主机的基本原理。4.2 多站点配置示例与宝塔面板端口修改假设我们有两个Tomcat实例一个跑订单系统一个跑后台系统。在Nginx的conf/nginx.conf的http块里可以并列写两个serverserver { listen 80; server_name app1.test.local; location / { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } server { listen 80; server_name app2.test.local; location / { proxy_pass http://127.0.0.1:8082; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }保存后nginx -t再nginx -s reload浏览器分别访问http://app1.test.local和http://app2.test.local你会发现虽然端口都是80但Nginx已经根据域名把请求分到不同的Tomcat上了。除了按域名区分还可以按端口区分。把两个server块的listen分别改成8081和8082server_name用相同的域名也行。这正好就是搜索热词里“多端口nginx 开发环境多站点自定义域名配置”的场景一个Nginx多个端口多个域名对应多个后端。如果你用的是宝塔面板这类服务器管理面板要注意区分“面板端口”和“Nginx站点端口”。宝塔面板自身的默认访问端口是8888这和Nginx服务本身没关系。想在宝塔里把某个Nginx站点改成非80端口入口是“站点设置 - 配置文件”找到listen 80改成listen 8080保存后到软件商店里的Nginx管理里点重载。另外宝塔面板自身的8888端口要改的话是在面板设置里改不是改Nginx配置两件事别混在一起。4.3 虚拟机场景的访问链路很多人会把练习环境搭在虚拟机上比如Windows本机装一个VMware虚拟机里跑Linux和Nginx。这时访问链路会多一层网络问题。虚拟机网络模式建议直接用NAT模式然后在VMware的设置里把宿主机的某个端口映射到虚拟机的80端口。比如设置宿主机8080端口转发到虚拟机80端口这样本机浏览器访问http://localhost:8080就能打到虚拟机的Nginx。如果不想做端口转发更直接的办法是让虚拟机和宿主机在同一网段也就是桥接模式虚拟机有独立的局域网IP例如192.168.1.100。然后修改Windows的hosts192.168.1.100 dev.test.localNginx里的server_name配成dev.test.local这样浏览器访问http://dev.test.local时请求会发到虚拟机的NginxNginx再根据规则把请求转发给虚拟机内的Tomcat或者转发给宿主机上跑的Tomcat前提是两个环境网络互通。我用这种模式练习过最常踩的坑是防火墙。虚拟机Linux里如果没开放80端口或者Windows防火墙禁了入站连接浏览器就会一直转圈或提示拒绝连接。所以配置完Nginx后先做连通性测试用curl -I http://localhost在虚拟机里确认Nginx本身正常工作再用宿主机访问虚拟机的IP一层层排查很快就能定位是防火墙还是Nginx配置的问题。5. 反代高频故障排查https证书报错与并发/超时问题5.1 net::err_cert_common_name_invalid的完整排查链路搜索热词里有一个非常具体的报错net::ERR_CERT_COMMON_NAME_INVALID。这个错误几乎都出现在HTTPS反向代理场景里。现象是访问Nginx的HTTPS地址时浏览器提示“服务器证书与此站点不匹配”之类的警告。根本原因是Nginx上使用的SSL证书里包含的域名CN或SAN和你实际访问的域名对不上。举个例子证书是给a.example.com签发的你却在访问b.example.comNginx虽然能把SSL握手做完但浏览器一比对证书里的域名和地址栏域名发现不一致就直接拦下来了。排查链路建议按这套来确认实际访问的域名是什么确认Nginx配置里server_name是否就是访问的域名。检查证书文件本身签发给了哪些域名用命令openssl x509 -in your_cert.pem -noout -text | grep -E Subject:|DNS:输出里的DNS:后面的列表就是证书绑定的域名清单。 3. 如果名字不匹配要么申请新证书要么把访问域名改成证书里存在的域名。 4. 如果本地练习没有正式证书自签证书一定要让客户端信任它用mkcert这类工具生成一个本机CA并导入系统信任区比手动导入一年自己签的.p12省心得多。顺带说一句HSTS的问题。如果你之前访问过这个域名浏览器强制HTTPS了即使你后面把证书换成匹配的也可能缓存了旧状态。处理办法是在开发阶段不启用HSTS或者用无痕窗口测试。5.2 最大并发链接数到底怎么算“nginx最大并发链接数老是用超”这个搜索词挺有意思很多人压测到某个临界点后Nginx就开始报错但不知道瓶颈在哪。Nginx能处理的连接数理论上由两个参数决定worker_processes 4; # 多少个worker进程 worker_connections 1024; # 每个worker能打开的连接数上限最大连接数约为worker_processes * worker_connections。但这里有个细节HTTP请求到来时一个客户端连接会占掉Nginx侧一个连接如果是反向代理Nginx还要向后端Tomcat建立一个连接所以一层代理场景下实际能扛住的客户端连接数大约是worker_processes * worker_connections / 2。如果打开了keep-alive长连接连接长时间不释放实际可用连接数会更紧张。提高并发上限有三个层面要做Nginx配置层把worker_processes设为auto让Nginx按CPU核心数自动分配worker_connections适当提高到2048或4096。操作系统层Nginx的连接数受系统文件描述符ulimit -n限制Linux下查看当前值用ulimit -n临时调大到65535用ulimit -n 65535永久修改看/etc/security/limits.conf。不调这个Nginx配置再高也白搭。后端层Tomcat的server.xml里maxThreads默认是200acceptCount默认是100。如果Tomcat线程池先被耗尽Nginx就算连接数再大转发过去的请求也会在后端排队直至超时。经常被忽视的一点是别把并发算成纯Nginx的事整条链路的短板是Tomcat。Nginx可以在连接层扛住海量请求但Tomcat处理不过来时Nginx的日志里就会大量出现upstream timed out或connection refused。5.3 “并发老是用超”和代理超时怎么调理“老是用超”这个描述通常是压测脚本里报连接超时或者请求超时。我会把现象和原因放在一起看Nginx的error.log里出现connect() failed (111: Connection refused) while connecting to upstream说明Nginx和后端Tomcat建立连接时被拒绝了。先检查Tomcat还活着没再看端口对不对。如果是压测中途出现很可能是Tomcat的acceptCount满了背压不过来系统直接拒了新的TCP连接。error.log里出现upstream timed out (110: Connection timed out) while reading response from upstream说明Nginx已经连接上后端但Tomcat在超时时间内没返回数据。这时要看的是proxy_read_timeout默认60秒后端接口处理时间超过60秒就会触发。和超时相关的三个Nginx参数proxy_connect_timeout 5s; # 和后端建立TCP连接的超时 proxy_read_timeout 60s; # 等待后端响应体的超时 proxy_send_timeout 60s; # 向后端发送请求体的超时我的经验是connect超时不能调太大本地或者内网环境超过5秒还不通基本就是网络或端口有问题调大只会掩盖故障。read超时则要根据业务接口的最慢耗时来定比如接口要跑一分半钟60秒就得调到120秒。但比调参更重要的是找到为什么这么慢。有一次压测一直报超时我翻了一下午Nginx日志最后还是从Tomcat的catalina.out里看到是数据库连接池被打满慢SQL把线程拖死了。Nginx只是把问题暴露出来的那个人它不是病根。6. Windows下查看nginx访问日志工具与姿势6.1 日志文件格式和理解在Windows上做练习时Nginx日志默认生成在解压目录的logs文件夹里两个文件最重要access.log负责记录每一次请求error.log负责记录报错。Nginx默认的日志格式是combined一条访问日志长这样127.0.0.1 - - [14/Jan/2026:10:23:45 0800] GET /api/order HTTP/1.1 200 198 http://app1.test.local/ Mozilla/5.0 ...拆开看就是客户端IP、用户标识通常是-、请求时间、请求方法、请求URI和协议版本、状态码、响应体大小、来源页面、用户浏览器User-Agent。查问题时先看状态码段500开头的服务端问题404是路径问题499是客户端提前断开。error.log可以设置级别生产里一般用error级别排查疑难问题可以临时调到debug但Nginx官方文档也提醒过debug级别日志量巨大只能局部开启别长期开着。6.2 靠谱的查看工具Windows没有Linux下那么好用的tail -f但有几种替代玩法都亲测可用PowerShell自带实时跟踪效果和Linux tail几乎一样Get-Content logs\access.log -Tail 50 -Wait加-Wait之后新产生的日志行会实时刷出来。我压测时基本就靠它盯error.log同时开两个PowerShell窗口一个盯错误一个盯访问。Notepad这类编辑器打开大文件会卡不建议用来调试实时日志如果只是翻历史日志可以用LogExpert它对GB级日志文件加载速度不错还能按列排序。想做统计报表推荐GoAccess。它有Windows版本直接生成HTML报告goaccess logs\access.log --log-formatCOMBINED -o report.html打开后能看到请求IP排名、状态码分布、访问时间热力图比肉眼一个一个翻快得多。排查问题时我会用一条命令快速筛选500状态码Select-String -Path logs\access.log -Pattern 500 看到的IP和时间点再回头配合error.log和Tomcat的日志对时间轴基本能把问题锁定在五分钟内。7. 容器化部署docker镜像与k8s套路7.1 用tomcat:8.5-jdk8-corretto跑一个容器容器化已经是部署的主流形态练习里加一步Docker很值。Docker Hub上Tomcat官方镜像的tag非常多热词里提到的tomcat:8.5-jdk8-corretto就是一个很经典的选择。为什么要推荐它而不是tomcat:latest因为latest标签的镜像基础JDK版本可能已经变成17甚至21老项目在JDK8下编译的代码跑在新JDK上很可能出问题。tomcat:8.5-jdk8-corretto意思是Tomcat 8.5版本配的是Amazom Corretto JDK 8。Corretto是JDK 8的一个长期支持发行版兼容性很稳。跑起来只需要两步docker pull tomcat:8.5-jdk8-corretto docker run -d --name tomcat-demo -p 8080:8080 tomcat:8.5-jdk8-corretto-d是后台运行-p 8080:8080把宿主机的8080端口映射到容器内的8080端口。容器起来后用docker exec -it tomcat-demo bash进入容器会看到熟悉的Tomcat目录结构。有个细节容易踩坑这个镜像的webapps目录里并没有默认的示例应用所以浏览器访问8080可能看到的是404或空目录。想部署自己的war包可以挂载volumedocker run -d --name tomcat-demo -p 8080:8080 -v D:/projects/webapp.war:/usr/local/tomcat/webapps/webapp.war tomcat:8.5-jdk8-corretto生产环境不会用docker exec进去乱改文件war包要么打进镜像要么通过挂载或CI/CD流水线放进去。7.2 docker-compose编排nginxtomcat如果想把Nginx和Tomcat一起用Docker跑建议直接用docker-compose一条命令拉起两个服务。下面是一份最小可用的docker-compose.ymlversion: 3 services: web: image: nginx:1.25 ports: - 80:80 volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro backend: image: tomcat:8.5-jdk8-corretto ports: - 8080:8080在nginx.conf里配置反向代理时proxy_pass的目标不能写127.0.0.1:8080了因为在同一个docker-compose网络里两个容器之间要通过服务名通信location / { proxy_pass http://backend:8080; }backend这个服务名在compose启动时会被写进容器的DNS解析里Nginx容器可以通过它找到Tomcat容器的IP地址。这个“容器间用服务名互访”的思路和虚拟机里用IP互访是两种不同的习惯初次接触容易迷糊但理解了容器网络之后就顺了。启动命令docker compose up -d然后用docker compose logs -f看日志。练习完成后docker compose down一键清理非常省心。7.3 k8s里部署nginxKubernetesK8s是容器编排层面的东西部署Nginx是它的入门必修课。部署一个Nginx需要三层资源Deployment管副本Service管访问入口Ingress管域名路由。Deployment是核心它声明了“我要跑几个Nginx副本”apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.25 ports: - containerPort: 80replicas: 2表示集群里会有两个Nginx Pod负载均衡和故障转移由K8s自动调度。有Deployment还不够Pod的IP是漂移的需要Service提供一个稳定的虚拟IP和DNS名字apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - port: 80 targetPort: 80 type: NodePortNodePort类型的Service会在集群每个节点上开一个固定端口外部通过节点IP:端口访问。如果集群里有Ingress Controller可以把域名和Service绑定apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx-ingress spec: rules: - host: app.test.local http: paths: - path: / pathType: Prefix backend: service: name: nginx-service port: number: 80这里面容易混淆的是K8s生态里不仅有“以Deployment方式部署Nginx”还有一个专门的Nginx Ingress Controller后者是整个集群的流量入口。简单理解前者是业务后者是网关。我们练习时先用Deployment方式跑通后续再研究Ingress Controller也不迟。8. 进阶玩法用nginx给ollama反代并注入apikey8.1 为什么本地大模型服务也需要反代最近很多人在本地跑大模型用的工具是Ollama。Ollama默认监听的是127.0.0.1:11434也就是只能本机访问。问题是如果你想让局域网里的其他电脑或者像Cherry Studio这类客户端来访问怎么办有些人图省事直接带参数启动ollama serve --host 0.0.0.0这样确实能让局域网访问了但11434端口完全裸奔局域网里任何人知道你的IP就能随便调你的模型还能删模型、改配置这就像把家门钥匙挂在门外只差贴个“欢迎光临”的纸条。正确做法是在前面加一层Nginx反代由Nginx统一负责端口暴露和鉴权Ollama继续监听本机回环地址。请求链路变成客户端 - Nginx判断Authorization头是否合法 - 合法才转发到127.0.0.1:11434 - Ollama这样即使Nginx暴露在局域网里没有正确的API Key的人也会在Nginx层直接被拦下连Ollama的入口都摸不到。8.2 配置与验证在Nginx的conf/nginx.conf里加上一个server监听11435端口假设我们不想暴露Ollama的默认11434转发目标指向本机的11434server { listen 11435; location / { if ($http_authorization ! Bearer ollama-secret-2026) { return 401; } proxy_pass http://127.0.0.1:11434; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这段配置的逻辑是所有请求必须先带Authorization: Bearer ollama-secret-2026的请求头不带或带错就返回401通过后才转发给Ollama。这里要说一句关于if的争议。Nginx社区有句名言叫“if is evil”意思是location里的if在某些场景下行为诡异比如和proxy_pass组合时可能出现意外跳转。但在这个简单鉴权场景里if返回401是最直接可行的写法只要不把if拿去处理复杂的rewrite就问题不大。验证步骤用nginx -t检查配置nginx -s reload重载。不带Key访问curl http://localhost:11435/api/tags应该收到401。 3. 带Key访问curl -H Authorization: Bearer ollama-secret-2026 http://localhost:11435/api/tags能返回Ollama的模型列表。在Cherry Studio这类客户端里把API Base地址填成http://你的Nginx地址:11435API Key填ollama-secret-2026连接测试就能通过。生产环境如果要让外部网络访问还要在这一层加上HTTPS否则密钥和内容都是明文传输。我做完这个练习最深的体会是很多安全问题不需要复杂的防火墙策略一个轻量级的反代入口配合简单的鉴权规则就能把风险面收得很小。Nginx的价值从来不只在于“把请求转过来”而是在转发这件事上衍生出的网关能力鉴权、限流、证书、路由全都可以在它这一层解决。
返回列表