点击HTML按钮无法调用Node.js,如何在同一服务器部署两者?
一、先解决当前的404错误与代码问题
你遇到的404错误主要是两个核心问题导致的,先把代码里的bug逐个修复:
Node.js服务未正确启动
你的Node代码最后一行是app.list(80),这是拼写错误!正确的方法是app.listen(80),少了字母e。这个错误会直接导致Node服务无法启动,自然无法处理/createContainer的请求,浏览器发起请求时就会返回404。端口冲突与请求路径不匹配
Apache默认监听80端口,你想让Node也占用80端口会导致冲突(同一端口不能同时被两个服务占用)。所以要么调整Node的端口,要么让Express直接托管静态文件替代Apache。补充必要的Express中间件(可选但推荐)
虽然你当前的POST接口没用到请求体,但为了后续扩展,建议添加解析请求的中间件;如果HTML和Node不在同一端口,还需要处理跨域问题:
先安装CORS依赖:npm install cors然后修改Node代码:
const express = require("express"); const app = express(); const cors = require('cors'); const process = require('child_process'); // 启用CORS,允许跨域请求 app.use(cors()); // 解析POST请求的表单数据 app.use(express.urlencoded({ extended: true })); app.post("/createContainer", (req, res) => { process.exec('kubectl apply -f tomcat.yaml',function (err,stdout,stderr) { if (err) { console.log("\n"+stderr); // 必须给客户端返回响应,否则浏览器请求会一直挂起 res.status(500).send(stderr); } else { console.log(stdout); res.status(200).send(stdout); } }); }); // 把端口改成3000,避免和Apache的80端口冲突 app.listen(3000, () => { console.log("Node server running on port 3000"); });修正HTML的Ajax请求路径
因为Node现在跑在3000端口,所以Ajax请求要指定完整地址:function myFunction() { $.post("http://你的服务器IP:3000/createContainer") .done((response) => { console.log("container created:", response); }) .fail((err) => { console.error("Request failed:", err); }); }另外,两个按钮都调用同一个
myFunction,你可能需要区分Deploy和Decommission操作,比如给按钮传参数:<button onclick="myFunction('deploy')" >Deploy</button> <button onclick="myFunction('decommission')">Decommission</button>后续可以在JS和Node代码里根据参数执行不同的kubectl命令(比如
kubectl delete用于销毁容器)。
二、如何在同一服务器上同时运行HTML和Node.js?
有三种可行方案,你可以根据需求选择:
方案1:用Express托管静态文件(替代Apache)
最简单的方式是把HTML文件放到Node项目的public文件夹里,让Express同时托管静态资源和API,不需要Apache:
- 在Node项目目录下新建
public文件夹,把web.html放进去。 - 修改Node代码,添加静态文件托管:
启动Node服务后,访问// 托管public目录下的静态文件 app.use(express.static('public'));http://你的服务器IP:3000/web.html就能看到页面,此时Ajax请求可以用相对路径/createContainer,因为页面和API在同一个服务下,不会有跨域问题。
方案2:用Apache做反向代理(保留Apache)
如果你想继续用Apache托管HTML,同时让Node处理API请求,可以配置Apache反向代理:
- 启用Apache的代理模块:
sudo a2enmod proxy proxy_http - 在Apache站点配置文件(比如
/etc/apache2/sites-available/000-default.conf)里添加规则:<VirtualHost *:80> # 原有的Apache配置,比如DocumentRoot /var/www/html # 把/api开头的请求转发到Node服务的3000端口 ProxyPass /api http://localhost:3000 ProxyPassReverse /api http://localhost:3000 </VirtualHost> - 重启Apache:
sudo systemctl restart apache2 - 修改Node代码的路由为
/api/createContainer,HTML里的Ajax请求改成/api/createContainer,这样用户访问HTML时不用加端口,Apache会自动把API请求转发给Node,也没有跨域问题。
方案3:跨域直接访问Node端口(仅测试用)
如果只是临时测试,可以让Node跑在3000端口,HTML里的Ajax请求直接指定http://你的服务器IP:3000/createContainer,同时在Node里启用CORS(前面代码已添加cors()中间件)。但这种方式在生产环境下不安全,不推荐长期使用。
最后提醒:运行Node服务时,要确保kubectl命令在Node进程的环境变量中可用,且Node进程有足够权限执行kubectl操作(比如当前用户有kubeconfig权限)。另外,建议用PM2管理Node服务,避免终端关闭后服务停止:
# 安装PM2 npm install -g pm2 # 启动Node服务并后台运行 pm2 start 你的Node文件名.js --name container-api
内容的提问来源于stack exchange,提问作者Swetha Swaminathan

