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

NextJS前后端应用Docker部署后后端服务失效求助

问题:NextJS Docker部署后后端API返回404,本地运行正常

我开发了一个兼具前端与后端功能的NextJS应用,本地运行yarn dev或执行yarn build后再运行yarn start均正常,但使用官方GitHub仓库的Dockerfile部署到Docker后,后端服务完全无法工作——手动访问API接口均返回NextJS的404页面。请问哪里操作出错了?

配置文件:next.config.js

module.exports = {
  output: 'standalone',
  async redirects() {
    return [
      {
        source: '/',
        destination: `/${process.env.COUNTRY_CODE}/login`,
        permanent: false,
        basePath: false,
      },
      {
        source: '/login',
        destination: `/${process.env.COUNTRY_CODE}/login`,
        permanent: false,
        basePath: false,
      },
    ]
  },
  basePath: `/${process.env.COUNTRY_CODE}`,
  trailingSlash: true,
  env: {
    CRMNX_COUNTRY_CODE: process.env.COUNTRY_CODE,
    NEXTAUTH_URL: process.env.NEXTAUTH_URL,
    NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
  }
};

配置文件:package.json

{
  "name": "myapp",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "node server.js",
    "watch": "nodemon server.js",
    "build": "next build",
    "start": "NODE_ENV=production node server.js"
  },
  "dependencies": {
    "@emotion/react": "^11.10.5",
    "@emotion/styled": "^11.10.5",
    "@headlessui/react": "^1.6.4",
    "@heroicons/react": "^1.0.6",
    "@mui/icons-material": "^5.10.9",
    "@mui/material": "^5.10.12",
    "@mui/x-date-pickers": "^5.0.8",
    "axios": "^0.27.2",
    "bootstrap": "^5.2.2",
    "cookie-session": "^2.0.0",
    "csurf": "^1.11.0",
    "date-format": "^4.0.14",
    "dayjs": "^1.11.6",
    "express": "^4.18.2",
    "express-rate-limit": "^6.4.0",
    "express-session": "^1.17.3",
    "formik": "^2.2.9",
    "iron-session": "^6.3.1",
    "jose": "^4.11.1",
    "jsonwebtoken": "^8.5.1",
    "libphonenumber-js": "^1.10.6",
    "moment": "^2.29.4",
    "mysql2": "^2.3.3",
    "next": "^13.0.6",
    "next-auth": "^4.17.0",
    "node-cache": "^5.1.2",
    "pure-react-carousel": "^1.30.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-device-detect": "^2.2.2",
    "react-hook-form": "^7.31.3",
    "react-phone-input-2": "^2.15.1",
    "sequelize": "^6.25.3",
    "sweetalert2": "^11.4.8",
    "yup": "^0.32.11"
  },
  "devDependencies": {
    "@babel/preset-react": "^7.18.6",
    "autoprefixer": "^10.4.7",
    "cors": "^2.8.5",
    "dotenv": "^16.0.1",
    "eslint": "8.20.0",
    "eslint-config-next": "^13.0.6",
    "nodemon": "^2.0.20",
    "postcss": "^8.4.14",
    "prettier": "2.7.1",
    "react-select": "^5.5.6",
    "sequelize-cli": "^6.5.2",
    "tailwindcss": "^3.0.24"
  }
}

配置文件:server.js

const next = require("next");
require('dotenv').config()

const port = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== "production";
const hostname = process.env.APP_HOSTNAME || "localhost";
const app = next({
  dev,
  hostname,
  port,
});
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const csrf = require("csurf");
  const cookieSession = require("cookie-session");

  const server = express();
  server.disable("x-powered-by");
  server.use(express.json());
  server.use(express.urlencoded({ extended: true }));

  server.use(
    cookieSession({
      name: "myapp.sid",
      keys: [process.env.APP_KEY],
      maxAge: 24 * 60 * 60 * 1000,
    })
  );

  const rateLimit = require("express-rate-limit");
  const limiter = rateLimit({
    windowMs: 15 * 60 * 1000,
    max: 100,
  });
  // server.use('/api', limiter)

  const router = require("./server/route");
  server.use(`/${process.env.COUNTRY_CODE}/api`, router);


  server.all("*", (req, res) => {
    return handle(req, res);
  });

  server.listen(port, (err) => {
    if (err) throw err;
    console.log(`> Ready on http://localhost:${port}`);
  });
});
问题排查与解决方案

1. Docker环境未正确设置COUNTRY_CODE环境变量

你的API路由前缀/${process.env.COUNTRY_CODE}/api和NextJS的basePath都依赖这个变量,但Docker容器不会自动加载本地.env文件。如果容器中该变量为空,API路由会变成无效的//api,请求直接被NextJS的404处理器捕获。

  • 解决办法:
    • 启动容器时显式传递变量:docker run -e COUNTRY_CODE=your_code ...
    • 若使用Docker Compose,在environment字段中添加该变量;或把.env文件复制到镜像中(注意不要包含敏感信息)。

2. output: 'standalone'模式下的文件路径问题

当启用standalone输出时,NextJS会生成精简的生产构建包。官方Dockerfile会把构建产物放到/app/.next/standalone目录,你需要确保:

  • server.js被正确复制到镜像的/app目录(与构建产物同路径)
  • ./server/route目录也被复制到镜像中,否则require("./server/route")会失败,API路由无法挂载
  • 检查Dockerfile是否包含类似以下的复制指令:
    COPY --from=builder /app/ ./
    COPY --from=builder /app/public ./public
    

3. API路由挂载顺序与有效性验证

确认COUNTRY_CODE变量生效后,检查API路由是否正确挂载:

  • 在server.js中添加日志,打印process.env.COUNTRY_CODE和挂载的路由路径,验证是否符合预期
  • 检查server/route中的路由定义,确保HTTP方法(GET/POST等)和路径与前端请求匹配

4. Docker端口映射是否正确

你的server.js默认监听3000端口,启动容器时必须用-p 3000:3000(或自定义端口映射)暴露端口,否则外部无法访问API接口。

内容的提问来源于stack exchange,提问作者felixbmmm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 13:15:32