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

Docker构建后Next.js图片优化器ECONNREFUSED错误排查与解决

Docker部署Next.js后Image组件加载后端图片报ECONNREFUSED错误的解决方法

问题概述

我开发的Next.js应用部署在Docker容器中,后端服务运行在9000端口,前端在3000端口。Avatar标签能正常加载后端的图片,但Next.js的Image组件无法显示图片,返回500内部服务器错误。

错误信息

GET http://localhost:3000/_next/image?url=http%3A%2F%2F127.0.0.1%3A9000%2Fuploads%2Fpublic%2Fbanners%2F1725328558480-LoneSamuraiSekiroWallpapers.jpg&w=1920&q=75 500 (Internal Server Error)
GET http://localhost:3000/_next/image?url=http%3A%2F%2F127.0.0.1%3A9000%2Fuploads%2Fpublic%2Fprofile-pictures%2F1725328558477-SamuraAndRaven.jpg&w=1920&q=75 500 (Internal Server Error)

TypeError: fetch failed
    at node:internal/deps/undici/undici:13179:13
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async fetchExternalImage (/app/node_modules/next/dist/server/image-optimizer.js:580:17)
    ...
[cause]: Error: connect ECONNREFUSED 127.0.0.1:9000

当前配置

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "http",
        hostname: "127.0.0.1",
        port: "9000",
        pathname: "/uploads/**",
      },
    ],
  },
};

export default nextConfig;

Image组件使用方式

<Image
  src={encodeURI(baseUrl + banner)}
  alt={`${name}'s banner`}
  objectFit="cover"
  layout="fill"
/>

Docker-compose.yml

version: "3.8"

services:
  db:
    image: postgres:14-alpine
    container_name: postgres-freetube-container
    ports:
      - "5432:5432" # Expose PostgreSQL port
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: freetube
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - freetube_network

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "9000:9000" # Expose the backend port
    environment:
      NODE_ENV: production
      DATABASE_URL: "postgresql://user:password@db:5432/freetube?schema=public" # Use the db service name as the host
      PORT: 9000
    depends_on:
      - db
    command: >
      sh -c "npx prisma migrate deploy && npm start"
    networks:
      - freetube_network

  frontend:
    build:
      context: ./freetube
      dockerfile: Dockerfile
    ports:
      - "3000:3000" # Expose the frontend port
    environment:
      NEXT_PUBLIC_API_BASE_URL: "http://backend:9000/api/" # Reference the backend service
      NEXT_PUBLIC_BASE_URL: "http://backend:9000/"
    depends_on:
      - backend
    networks:
      - freetube_network
    # env_file:
    #   - .env # Ensure the .env file is correctly referenced

volumes:
  db_data:

networks:
  freetube_network:
    driver: bridge

补充信息

  • 直接在浏览器访问图片URL可以正常加载;
  • Next.js图片优化器尝试从后端获取图片时抛出ECONNREFUSED错误;
  • 前端和后端都运行在Docker容器中。

已尝试操作

  • 确认后端服务在9000端口正常运行;
  • 验证图片可在浏览器中正常加载。

解决方案

问题核心是Docker容器间的网络访问逻辑:

  1. Next.js的Image组件在服务端渲染时,会由Node.js服务去请求图片资源。此时前端容器内的127.0.0.1指向容器自身,而非宿主机,所以无法访问到后端容器。
  2. 而Avatar标签是客户端直接请求图片,浏览器用宿主机的127.0.0.1:9000可以访问到映射的后端端口,所以正常。

步骤1:修改next.config.js的图片远程配置

把remotePatterns中的hostname改成Docker-compose里的后端服务名backend,因为同一Docker网络内可以通过服务名直接访问:

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "http",
        hostname: "backend", // 替换为服务名
        port: "9000",
        pathname: "/uploads/**",
      },
    ],
  },
};

export default nextConfig;

步骤2:区分服务端与客户端的图片baseUrl

在代码中判断运行环境,服务端使用容器内的服务地址,客户端使用宿主机地址:

// 定义baseUrl,区分服务端和客户端
const baseUrl = typeof window === 'undefined' 
  ? 'http://backend:9000' // 服务端渲染时用容器服务名访问
  : 'http://localhost:9000'; // 客户端用宿主机地址

// Image组件使用
<Image
  src={encodeURI(baseUrl + banner)}
  alt={`${name}'s banner`}
  objectFit="cover"
  layout="fill"
/>

步骤3:重启容器

修改配置后,重新构建并启动Docker容器:

docker-compose down
docker-compose up --build

这样调整后,Next.js服务端渲染时会通过Docker网络访问后端容器获取图片,客户端则通过宿主机端口访问,两者都能正常加载图片,解决ECONNREFUSED错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:55:55