Nuxt3中调用useFetch()在Docker容器触发Vue Router错误
Nuxt 3 + Docker:容器内useFetch请求触发Vue Router错误,且出现套接字占用问题
环境版本
- Nuxt 3.10.2
- Docker 25.0.3
- Node.js 20.9
问题描述
本地执行npm run dev时应用运行正常,但Docker容器中启动后出现两个核心问题:
- Vue Router匹配错误:所有
useFetch请求触发No match found for location with path "/api/v1/xxx"警告,API请求无法正确发送到后端,应用无法响应请求。 - 套接字地址占用:容器启动后页面无法打开,抛出
listen EADDRINUSE: address already in use /tmp/nitro/worker-xx-x.sock错误。
容器启动日志(Vue Router错误阶段)
> docker-compose -f docker-compose.local.yml up [+] Running 1/2 ✔ Network frontend Created 0.1s - Container frontend Created 0.2s Attaching to frontend frontend | frontend | > dev frontend | > nuxt dev frontend | frontend | Nuxt 3.10.2 with Nitro 2.8.1 frontend | frontend | [QR code] frontend | frontend | ➜ Local: http://0.0.0.0:/ frontend | ➜ Network: http://172.19.0.4:/ [QR code] frontend | ➜ Network: http://172.20.0.2:/ frontend | frontend | [nuxt:tailwindcss] ℹ Using default Tailwind CSS file frontend | ℹ Compiled types/plugins.d.ts in 774.5ms frontend | ℹ Compiled plugins/server.mjs in 769.24ms frontend | ℹ Compiled plugins/client.mjs in 798.45ms frontend | ℹ Vite server warmed up in 76990ms frontend | ℹ Vite client warmed up in 82499ms frontend | [nitro] ✔ Nitro built in 4538 ms frontend | [Vue Router warn]: No match found for location with path "/api/v1/user/profile" frontend | [Vue Router warn]: No match found for location with path "/api/v1/user/profile" ...(省略重复警告)
后续套接字占用错误日志
frontend | ➜ Local: http://0.0.0.0:/ frontend | ➜ Network: http://172.21.0.2:/ [QR code] frontend | frontend | [nuxt:tailwindcss] ℹ Using default Tailwind CSS file frontend | ℹ Vite server warmed up in 43668ms frontend | ℹ Vite client warmed up in 52475ms frontend | [nitro] ✔ Nitro built in 2394 ms frontend | [nitro] [uncaughtException] Error: listen EADDRINUSE: address already in use /tmp/nitro/worker-30-1.sock frontend | at Server.setupListenHandle [as _listen2] (node:net:1880:21) frontend | at listenInCluster (node:net:1945:12) frontend | at Server.listen (node:net:2054:5) frontend | at <anonymous> (/src/node_modules/nitropack/dist/runtime/entries/nitro-dev.mjs:26:25) frontend | at ModuleJob.run (node:internal/modules/esm/module_job:222:25) frontend | at async ModuleLoader.import (node:internal/modules/esm/loader:323:24) frontend | at async loadESM (node:internal/process/esm_loader:28:7) frontend | at async handleMainPromise (node:internal/run_main:113:12) { frontend | code: 'EADDRINUSE', frontend | errno: -98, frontend | syscall: 'listen', frontend | address: '/tmp/nitro/worker-30-1.sock', frontend | port: -1 frontend | }
相关代码
插件文件:./plugins/loadCity.ts
import {useCityStore} from "~/store/useCityStore"; export default defineNuxtPlugin(async (nuxtApp) => { const location = useCityStore(); if(!location.currentCity){ await location.fetchCity(); // 触发错误: No match found for location with path "/api/v1/city/get" } });
Pinia Store:/store/useCityStore.ts
import { defineStore } from "pinia"; export const useCityStore = defineStore('location', () => { async function fetchCity() { const {data} = await useApiFetch(`/api/v1/city/get`); // 其他逻辑 } return { fetchCity } });
自定义Fetch钩子:useApiFetch.ts
export function useApiFetch<T> (path: string|(() => string)|ComputedRef<string>, options: UseFetchOptions<T> = {}) { const config = useRuntimeConfig() const xsrfToken = useCookie('XSRF-TOKEN'); let headers: any = { accept: 'application/json', referer: config.public.api.referer, ...options?.headers, } if (xsrfToken && xsrfToken.value !== null) { headers['X-XSRF-TOKEN'] = xsrfToken.value as string; } if (process.server) { headers = { ...headers, ...useRequestHeaders(['cookie']), } } return useFetch(path, { baseURL: config.public.api.url, watch: false, credentials: 'include', ...options, headers, }) }
Docker配置
Dockerfile.dev
# syntax = docker/dockerfile:1 ARG NODE_VERSION=20.9 FROM node:${NODE_VERSION}-slim as base ENV NODE_ENV=development WORKDIR /src # Build FROM base as build COPY --link package.json package-lock.json ./ RUN npm install # Run FROM base COPY --from=build /src/node_modules /src/node_modules CMD [ "npm", "run", "dev" ]
docker-compose.yml
version: '3.7' services: frontend: container_name: frontend build: context: . dockerfile: ./Dockerfile.dev restart: always volumes: - ./:/src - node_modules:/src/node_modules working_dir: /src expose: - 80 - 24678 ports: - "24678:24678" environment: NODE_OPTIONS: '--max_old_space_size=4096' VIRTUAL_HOST: $FRONTEND_DOMAIN LETSENCRYPT_HOST: $FRONTEND_DOMAIN LETSENCRYPT_EMAIL: "le@bybuy.kz" HTTPS_METHOD: noredirect VIRTUAL_PORT: 80 NITRO_PORT: 80 NITRO_HOST: 0.0.0.0 PORT: 80 NUXT_SITE_URL: $NUXT_SITE_URL NUXT_API_URL: $NUXT_API_URL NUXT_API_REFERRER: $NUXT_API_REFERRER NUXT_SEARCH_API_KEY: $NUXT_SEARCH_API_KEY NUXT_SEARCH_HOST: $NUXT_SEARCH_HOST NUXT_SEARCH_PORT: $NUXT_SEARCH_PORT NUXT_SEARCH_PROTOCOL: $NUXT_SEARCH_PROTOCOL networks: - frontend - reverse-proxy networks: reverse-proxy: name: reverse-proxy external: true frontend: name: frontend driver: bridge volumes: node_modules:
已尝试的排查
- 排除代理问题:直接启动容器不使用反向代理,发送HTTP请求仍复现Vue Router错误。
排查与解决方案
针对Vue Router匹配错误
验证环境变量正确性
- 确认容器内
NUXT_API_URL已正确注入,且值为容器可访问的后端地址(避免使用localhost,容器内localhost指向自身,需改用宿主机IP或Docker服务名)。 - 在
useApiFetch中添加调试日志,打印config.public.api.url,确认baseURL是否正确:console.log('API Base URL:', config.public.api.url);
- 确认容器内
检查Nuxt运行时配置
- 确保
nuxt.config.ts中已正确暴露api.url和api.referer到客户端:export default defineNuxtConfig({ runtimeConfig: { public: { api: { url: process.env.NUXT_API_URL, referer: process.env.NUXT_API_REFERRER } } } })
- 确保
确认网络连通性
- 进入容器内部,执行
curl <NUXT_API_URL>/api/v1/city/get,验证是否能正常访问后端API:docker exec -it frontend bash curl $NUXT_API_URL/api/v1/city/get
- 进入容器内部,执行
针对套接字地址占用错误
清理残留套接字文件
- 修改Dockerfile的CMD,启动前清理Nitro临时套接字:
CMD ["sh", "-c", "rm -rf /tmp/nitro/ && npm run dev"]
- 修改Dockerfile的CMD,启动前清理Nitro临时套接字:
强制清理容器资源
- 停止并删除容器及相关卷,避免残留进程或文件:
docker-compose down -v docker-compose up --build
- 停止并删除容器及相关卷,避免残留进程或文件:
指定Nitro使用端口而非套接字
- 在环境变量中添加
NITRO_PRESET=node-server,强制Nitro使用端口监听而非Unix套接字:# docker-compose.yml中frontend的environment添加 NITRO_PRESET: node-server
- 在环境变量中添加
检查容器重启策略
- 暂时将
restart: always改为restart: no,避免容器频繁重启导致资源泄漏,排查问题根源。
- 暂时将
内容的提问来源于stack exchange,提问作者Olexin
相关产品推荐
相关产品推荐

