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

预生产环境Nuxt前端无法调用Strapi GraphQL端点问题

问题描述

预生产环境部署了Nuxt前端+Strapi后端,采用Docker镜像部署前端、后端及Nginx。预生产前端容器无法获取Strapi的GraphQL端点,但本地前端连接预生产后端可正常工作。前端容器日志报错:

---> ERROR >  Network error: request to https://mydomain.dev/graphql failed, reason: connect ETIMEDOUT 161.35.150.4:443

  at new ApolloError (node_modules/apollo-client/bundle.umd.js:92:26)
  at node_modules/apollo-client/bundle.umd.js:1588:34
  at node_modules/apollo-client/bundle.umd.js:2008:15
  at Set.forEach (<anonymous>)
  at node_modules/apollo-client/bundle.umd.js:2006:26
  at Map.forEach (<anonymous>)
  at QueryManager.broadcastQueries (node_modules/apollo-client/bundle.umd.js:2004:20)
  at node_modules/apollo-client/bundle.umd.js:1483:29
  at processTicksAndRejections (node:internal/process/task_queues:96:5)
Error Network error: request to https://mydomain.dev/graphql failed, reason: connect ETIMEDOUT XXX.XXX.XXX.XXX:443
 ---> ERROR >  Network error: request to https://mydomain.dev/graphql failed, reason: connect ETIMEDOUT 161.35.150.4:443 

相关配置文件

nginx.conf

events{}

http{
  include mime.types;

  # Expires map
  map $sent_http_content_type $expires {
      default                    off;
      text/html                  epoch;
      text/css                   max;
      application/javascript     max;
      ~image/                    max;
  }

  server {
    listen 80;
    listen [::]:80;

    server_name mydomain.com;
    server_tokens off;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    

    location / {
        return 301 https://mydomain.dev$request_uri;
    }
  }

  server {
    listen 443 default_server ssl;
    listen [::]:443 ssl;

    server_name mydomain.dev;

    ssl_certificate /etc/nginx/ssl/live/mydomain.dev/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/live/mydomain.dev/privkey.pem;
    
    location /admin {
      sendfile on;
      proxy_pass http://backend:1337;
    }
    
    location /graphql {
      sendfile on;
      proxy_pass http://backend:1337;
    }

    location / {
      sendfile on;
      proxy_pass http://frontend:3000;
    }
  }
}

docker-compose.yml

# path: ./docker-compose.yml

version: '3'
services:
  certbot:
    image: certbot/certbot:latest
    volumes:
      - ./certbot/www/:/var/www/certbot/:rw
      - ./certbot/conf/:/etc/letsencrypt/:rw
  frontend:
    container_name: frontend
    image: mydockerhub/app-front:latest
    restart: always
    ports:
      - 3000:3000
  backend:
    container_name: backend
    build: .
    image: mydockerhub/app-back
    restart: always
    env_file: .env
    environment:
      DATABASE_CLIENT: ${DATABASE_CLIENT}
      DATABASE_HOST: myDB
      DATABASE_PORT: ${DATABASE_PORT}
      DATABASE_NAME: ${DATABASE_NAME}
      DATABASE_USERNAME: ${DATABASE_USERNAME}
      DATABASE_PASSWORD: ${DATABASE_PASSWORD}
      JWT_SECRET: ${JWT_SECRET}
      ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
      APP_KEYS: ${APP_KEYS}
      NODE_ENV: ${NODE_ENV}
    ports:
      - '1337:1337'
    depends_on:
      - myDB
    volumes:
      - ./app:/srv/app

  myDB:
    container_name: myDB
    platform: linux/amd64 #for platform error on Apple M1 chips
    restart: unless-stopped
    env_file: .env
    image: mysql:5.7
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD}
      MYSQL_PASSWORD: ${DATABASE_PASSWORD}
      MYSQL_DATABASE: ${DATABASE_NAME}
    volumes:
      - strapi-data:/var/lib/mysql
      #- ./data:/var/lib/mysql # if you want to use a bind folder
    ports:
      - '13306:3306'
  webserver:
    container_name: webserver
    image: nginx:latest
    ports:
      - 80:80
      - 443:443
    restart: always
    depends_on:
      - frontend
      - backend
    volumes:
      - ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certbot/www:/var/www/certbot/:ro
      - ./certbot/conf/:/etc/nginx/ssl/:ro

volumes:
  strapi-data:
问题分析

前端容器内部访问外部域名https://mydomain.dev/graphql超时,核心原因是:

  1. Docker容器所在网络环境可能存在防火墙限制、路由问题,导致无法直接解析或访问外部域名
  2. 更关键的是,Docker Compose默认会创建统一网络,前端容器可直接通过服务名访问后端,无需走Nginx外部域名。本地前端能正常访问,是因为本地环境可解析外部域名并通过公网/局域网访问预生产Nginx端口。
解决方案

方案1:修改前端GraphQL端点配置

将前端中配置的GraphQL地址从https://mydomain.dev/graphql改为http://backend:1337/graphql。Docker Compose网络内的服务可通过服务名(backend)直接通信,无需经过Nginx反向代理,既高效又避免网络问题。

  • Nuxt项目通常在nuxt.config.js或Apollo专属配置文件中修改端点
  • 推荐通过环境变量传递该内部地址,方便不同环境切换,确保镜像构建时配置正确

方案2:调整容器网络(可选)

若必须通过Nginx访问后端,可将GraphQL地址改为http://webserver/graphql(Nginx容器监听80端口,内部访问无需HTTPS),但这种方式多了一层代理,效率不如直接访问后端。

方案3:检查容器网络连通性

进入前端容器测试网络连通性,排查是否存在网络故障:

docker exec -it frontend ping backend
docker exec -it frontend curl http://backend:1337/graphql

若无法ping通或curl失败,需检查Docker网络配置,确保所有服务处于同一网络(Docker Compose默认会创建统一网络,一般无需手动配置)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 23:15:51