You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击HTML按钮无法调用Node.js,如何在同一服务器部署两者?

问题分析与解决方案

一、先解决当前的404错误与代码问题

你遇到的404错误主要是两个核心问题导致的,先把代码里的bug逐个修复:

  1. Node.js服务未正确启动
    你的Node代码最后一行是app.list(80),这是拼写错误!正确的方法是app.listen(80),少了字母e。这个错误会直接导致Node服务无法启动,自然无法处理/createContainer的请求,浏览器发起请求时就会返回404。

  2. 端口冲突与请求路径不匹配
    Apache默认监听80端口,你想让Node也占用80端口会导致冲突(同一端口不能同时被两个服务占用)。所以要么调整Node的端口,要么让Express直接托管静态文件替代Apache。

  3. 补充必要的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");
    });
    
  4. 修正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代码,添加静态文件托管:
    // 托管public目录下的静态文件
    app.use(express.static('public'));
    
    启动Node服务后,访问http://你的服务器IP:3000/web.html就能看到页面,此时Ajax请求可以用相对路径/createContainer,因为页面和API在同一个服务下,不会有跨域问题。

方案2:用Apache做反向代理(保留Apache)

如果你想继续用Apache托管HTML,同时让Node处理API请求,可以配置Apache反向代理:

  1. 启用Apache的代理模块:
    sudo a2enmod proxy proxy_http
    
  2. 在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>
    
  3. 重启Apache:
    sudo systemctl restart apache2
    
  4. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:14:21