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
相关产品推荐
相关产品推荐

