SvelteKit服务端调用Docker内GraphQL接口遇ECONNREFUSED错误
SvelteKit容器调用另一Docker容器API失败问题解决
问题描述
在SvelteKit的服务端动作文件(+page.server.js)中,使用框架提供的fetch方法调用API接口。当前SvelteKit服务部署在端口为8000的Docker容器内,目标API是部署在另一端口为8002的Docker容器中的GraphQL服务。
服务端动作代码:
import { fail } from '@sveltejs/kit' export const actions = { default: async ({ request, cookies, fetch }) => { const form = await request.formData() const username = form.get('username') const password = form.get('password') if (!username || !password) return fail(400, { username }) const result = await fetch('http://localhost:8002/sessions', { method: 'POST', headers: { 'Content-Type': 'application/json', }, // Omitted because it doesn't appear to be the cause of this issue. body: JSON.stringify({}), }) console.log({result}) } }
调用时抛出连接拒绝错误:
TypeError: fetch failed at node:internal/deps/undici/undici:13484:13 at process.processTicksAndRejections (node:internal/process/task_queues:105:5) { [cause]: Error: connect ECONNREFUSED 127.0.0.1:8002 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1615:16) at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) { errno: -111, code: 'ECONNREFUSED', syscall: 'connect', address: '127.0.0.1', port: 8002 } }
已尝试替换localhost为127.0.0.1,问题仍存在;但在宿主机用Postman调用相同接口可正常运行,问题出在容器间的连接逻辑上。
解决方法
核心原因
Docker容器内的localhost或127.0.0.1指向容器自身,而非宿主机。Postman在宿主机运行能访问宿主机映射的8002端口,但SvelteKit容器内的请求会尝试连接自身的8002端口,导致连接被拒绝。
具体方案
- 同一Docker Compose网络下用服务名访问:如果两个容器通过Docker Compose部署,直接使用目标服务在
docker-compose.yml中定义的服务名作为地址。例如目标服务名为graphql-api,则请求地址改为http://graphql-api:8002/sessions,Docker会自动通过服务名解析到对应容器的IP。 - 使用宿主机局域网IP:若容器不在同一Compose网络,将请求地址中的
localhost替换为宿主机的局域网IP(如192.168.1.100),同时确保目标容器的8002端口已映射到宿主机,且宿主机防火墙允许容器访问该端口。 - 统一Docker网络:手动创建Docker网络,并将两个容器加入该网络,确保容器间能互相通信,之后即可通过容器名或服务名访问。
内容的提问来源于stack exchange,提问作者Chris Peters
相关产品推荐
相关产品推荐

