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

Apollo Gateway在Docker内无法连接GraphQL服务问题排查

Apollo Gateway无法连接Docker Compose中的GraphQL子服务

我的项目运行两个GraphQL API,通过Apollo Gateway实现聚合。执行Docker Compose后,API服务能正常构建并通过浏览器访问,但Gateway始终无法连接这些子服务。

我知道这类问题通常是因为Gateway指向http://localhost:port/graphql而非http://service:port/graphql,但修改后仍报错:

gateway | Error: Couldn't load service definitions for "images" at http://images:3000: request to http://images:3000/ failed, reason: connect ECONNREFUSED 172.25.0.4:3000

已尝试的操作:

  • 在Gateway的app.module.ts中添加/graphql路径
  • 为Docker Compose配置自定义网络
  • 进入Gateway容器ping其他服务,能正常解析服务名称

本地启动服务命令:

  • pnpm start:dev images 启动images服务
  • pnpm start:dev products 启动products服务
  • pnpm start:dev 启动Gateway

各服务Dockerfile

FROM node:18-alpine
 
WORKDIR /usr/src/app
 
RUN npm install -g pnpm
 
COPY package.json pnpm-lock.yaml ./
 
RUN pnpm install
 
COPY . .
 
EXPOSE 3000

CMD ["pnpm", "start:dev", "images"]

Docker Compose配置文件

version: '3'
services:
  database:
    container_name: database
    image: 'postgres:latest'
    ports:
      - 5432:5432
    restart: always
    env_file:
      - .env
    volumes:
      - ${PWD}/db-data/:/var/lib/postgresql/data/
      - ${PWD}/init.sql:/docker-entrypoint-initdb.d/init.sql

  images:
    container_name: images
    build: 
      context: .
      dockerfile: ./apps/images/Dockerfile
      args:
        - SERVICE_NAME=images
    ports:
      - 3000:3000
    env_file:
      - .env
    depends_on:
      - database
    

  products:
    container_name: products
    build:
      context: .
      dockerfile: ./apps/products/Dockerfile
      args:
        - SERVICE_NAME=products
    ports:
      - 3001:3001
    env_file:
      - .env
    depends_on:
      - database

  gateway:
    container_name: gateway
    build:
      context: .
      dockerfile: ./apps/gateway/Dockerfile
    ports:
      - 3002:3002
    environment:
      - PRODUCTS_HOST=products:3001
      - IMAGES_HOST=images:3000
    depends_on:
      - database
      - products
      - images


volumes:
  postgres_data:
    driver: local

Gateway的app.module.ts代码

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloGatewayDriver, ApolloGatewayDriverConfig } from '@nestjs/apollo';
import { IntrospectAndCompose } from '@apollo/gateway';

const productsHost = process.env['PRODUCTS_HOST'] || 'localhost:3001';
const imagesHost = process.env['IMAGES_HOST'] || 'localhost:3000';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloGatewayDriverConfig>({
      driver: ApolloGatewayDriver,
      server: {
        csrfPrevention: false,
      },
      gateway: {
        supergraphSdl: new IntrospectAndCompose({
          subgraphs: [
            {
              name: 'images',
              url: `http://${imagesHost}`,
            },
            {
              name: 'products',
              url: `http://${productsHost}`,
            },
          ],
        }),
      },
    }),
  ],
})
export class AppModule {}

docker ps运行结果

CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS          PORTS                                       NAMES
6f81e45e1d49   gateway-gateway    "docker-entrypoint.s…"   38 seconds ago   Up 37 seconds   0.0.0.0:3002->3002/tcp, :::3002->3002/tcp   gateway
cf77b2cd277b   gateway-products   "docker-entrypoint.s…"   38 seconds ago   Up 37 seconds   0.0.0.0:3001->3001/tcp, :::3001->3001/tcp   products
f02de42daed3   gateway-images     "docker-entrypoint.s…"   38 seconds ago   Up 37 seconds   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp   images
77e194ce3169   postgres:latest    "docker-entrypoint.s…"   38 seconds ago   Up 37 seconds   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   database

问题分析与解决建议

  1. 服务启动顺序问题:depends_on仅保证容器启动顺序,不确保服务完全就绪。子服务可能还在等待数据库连接或初始化,此时Gateway尝试连接会失败。

    • 解决:给Gateway添加启动延迟,或在Docker Compose中为子服务配置healthcheck,让Gateway仅在子服务健康后启动。
  2. 子服务绑定地址问题:本地开发时服务默认绑定localhost,但Docker容器中需要绑定0.0.0.0才能被其他容器访问。检查子服务的NestJS配置,确保listen方法绑定'0.0.0.0'而非'localhost':

    await app.listen(3000, '0.0.0.0');
    
  3. 子服务GraphQL路径问题:Apollo Gateway默认访问子服务根路径,但NestJS的GraphQL端点默认是/graphql。需要在Gateway的子服务URL中明确添加该路径:

    {
      name: 'images',
      url: `http://${imagesHost}/graphql`,
    },
    {
      name: 'products',
      url: `http://${productsHost}/graphql`,
    },
    
  4. 网络连通性验证:进入Gateway容器执行curl http://images:3000/graphql,测试是否能正常访问子服务端点,确认端口是否真的开放。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:04:53