预生产环境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超时,核心原因是:
- Docker容器所在网络环境可能存在防火墙限制、路由问题,导致无法直接解析或访问外部域名
- 更关键的是,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
相关产品推荐
相关产品推荐

