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

Docker中React无法加载public目录运行时生成的图片问题

问题描述

我在Docker中运行Node服务与React前端,二者共享/public目录的卷。Docker构建阶段,/public目录仅存在output1.png;运行阶段,Node服务接收图片并写入卷生成input1.png等文件。我在两个容器的Docker文件系统中均能看到input1.png和output1.png,且取出的input1.png为有效图片,但React中仅output1.png可正常显示,localhost:3000/input1.png无法访问。我怀疑这是Docker相关问题,比如仅构建时存在的文件才被JavaScript运行时认可?


服务端图片保存代码

//  a zmq subscriber that reads from zmq and publishes over websocket to react.
//  react apps can't directly read from zmq, so we need to use this server to bridge the gap.

// zmq subscriber initialized here
var zmq = require("zeromq"),
  sock = zmq.socket("sub");

// ws server initialized here to send data to react
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 6002 });
let currentData = {};

let count = 0;
sock.bindSync(`tcp://*:6001`, (err) => { // bind fails because we don't wait for bind or smth, bindSync works
  if (err) throw err;
  console.log(`ZeroMQ publisher bound to port 6001`);
});sock.subscribe("");
console.log("Subscriber connected to port 6001");

sock.on('message', function(message) {
    try {
        count += 1;
        currentData = JSON.parse(message);
        const image_count = { type: 'image_count', value: count };
        currentData.push(image_count);
        wss.clients.forEach(function each(client) {
            if (client.readyState === WebSocket.OPEN) {
                client.send(JSON.stringify(currentData));
            }
        });
        const fs = require('fs');
        const imageObject = currentData.find(item => item.type === 'composite_image');
        const image_rcvd = Buffer.from(imageObject.image, 'base64');
        const filename = `public/input${count}.png`;
        fs.writeFile(filename, image_rcvd, function(err) {
          if (err) {
            console.log('Error:', err);
          } else {
            console.log('Image saved');
          }
        });
        currentData = currentData.filter(item => item.type !== 'composite_image'); // Remove the "composite_image" object
        console.log(currentData);
    } catch (error) {
        console.error('Error parsing ZMQ message:', error);
    }
});

// ws server connection
wss.on('connection', function connection(ws) {
    console.log('WebSocket client connected');

    ws.on('close', function close() {
        console.log('WebSocket client disconnected');
    });
});

console.log("WebSocket server started on ws://0.0.0.0:6002");

Leaflet地图相关图片加载代码

if (imageData.image_count !== 0) {
      console.log("adding image");
      let filename = process.env.PUBLIC_URL + "/input" + imageData.image_count + ".png";
      console.log(filename);
      try {
        let overlay = L.imageOverlay.rotated(filename, imageData.topleft, imageData.topright, imageData.bottomleft).addTo(map);
        console.log(overlay);
      } catch (error) {
        console.log(error);
      }

React Dockerfile

# react
FROM node:14
WORKDIR /app


COPY package.json .
COPY package-lock.json .

RUN npm install
RUN npm install -g serve

COPY . .
RUN npm run build
# server on 3001
EXPOSE 3001
CMD ["serve", "-s", "build", "-l", "3001"]

Node服务端Dockerfile

# server
FROM node:14
WORKDIR /app


COPY package.json .
COPY package-lock.json .

RUN npm install

COPY . .
RUN npm run build

CMD ["node", "server.js"]

解决方案

问题核心不是JavaScript运行时的限制,而是React容器的静态资源服务配置问题:React容器用serve -s build提供资源,但build目录是构建阶段生成的,运行时新增的图片在共享的/app/public目录,不在serve的默认资源路径里,所以无法访问。

方案一:修改React容器的serve配置

调整React Dockerfile的CMD命令,让serve同时提供build和public目录的静态资源:

CMD ["serve", "-s", "build", "-s", "public", "-l", "3001"]

这样运行时新增的input1.png就能通过React容器的端口访问到。

方案二:让Node服务端提供静态图片服务

既然Node服务端已经能访问到共享卷里的图片,可以在Node服务中添加静态文件服务:

  1. 安装express依赖:npm install express
  2. 修改server.js,添加静态资源服务:
const express = require('express');
const app = express();
// 将public目录设为静态资源目录
app.use(express.static('public'));
// 启动静态文件服务在6003端口
app.listen(6003, () => {
  console.log('Static file server running on port 6003');
});
  1. 修改React中的图片路径,指向Node服务的地址:
let filename = "http://node-server:6003/input" + imageData.image_count + ".png";

注意要确保React容器和Node服务在同一个Docker网络中,能互相访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:30:01