【问题标题】:Serve static react app with nodejs through docker通过 docker 为 nodejs 提供静态反应应用程序
【发布时间】:2020-10-18 10:52:15
【问题描述】:

我有节点的目录,反应如下:

Project
 + client
   + admin
      + build
          + index.html
 + server_api
   + server.js
   + Dockerfile
 
 + docker-compose.yml

docker-compose 文件

  server_api:
    container_name: speed_react_server_api
    build:
        context: ./server_api
        dockerfile: Dockerfile
    image: speed_react/server_api
    ports:
        - "5000:5000"
    volumes:
        - ./server_api:/usr/src/app

我的 server.js 像这样从 react 应用程序提供静态文件:

app.get('*', (req, res) => {
    res.sendFile(path.resolve(__dirname, '../client/admin/', 'build', 'index.html'));
});

但它似乎不起作用。 我不想将文件夹 client 移动到 server

你能建议我解决办法吗?

【问题讨论】:

    标签: node.js reactjs docker


    【解决方案1】:

    更新:

    @David 给出了一个答案,最好用多阶段构建 Docker 映像。

    另一种方法是构建唯一的API,因为客户端没有依赖,所以你可以挂载clinet with API

      server_api:
        container_name: speed_react_server_api
        image: abc
        ports:
            - "4001:4001"
        entrypoint: sh -c "cd /usr/src/app/server_api/; node server.js"
        volumes:
            - ./server_api/:/usr/src/app/server_api/
            - ./client/:/usr/src/app/client/ 
    

    你没有提到错误,但我认为脚本不服务于分发。

    但您似乎缺少express-static-files 配置。

    要提供静态文件,例如图像、CSS 文件和 JavaScript 文件,请使用 Express 中的 >express.static 内置中间件函数。

    函数签名是:

    express.static(root, [options])
    

    这是完整的脚本

    const express = require('express');
    const path = require('path');
    const app = express();
    const PORT=process.env.PORT | 4001
    app.use(express.static('../client/admin/build/dist', {
      maxAge: '31557600' 
    }))
    
    var compress = require('compression');
    app.use(compress()); 
    
    app.use('/', express.static('../client/admin/build/dist/', { redirect: false }));
    
    app.get('*', (req, res) => {
      res.sendFile(path.resolve('../client/admin/build/dist/index.html'));
    });
    
    app.listen(PORT, () => {
      console.log(`Incentive frontend is listening on ${PORT}`);
    });
    

    【讨论】:

    • 感谢您的回答,但您可能误解了我的问题。由于 react 应用程序不在 Dockerfile 的文件夹中,因此 server.js 无法读取它。我想要一个解决方案。如果在 node 的文件夹中 react app,它运行良好。
    • 哦,知道了,@David 已经给出了一个答案,正在更新另一种方法的答案。
    【解决方案2】:

    您可以根据需要在Dockerfile 中重新排列文件。

    请注意,这将需要删除 volumes: 行,这(可能)会导致整个 Dockerfile 大部分被忽略。您的 Docker 容器将无法用作开发环境。主机节点非常易于安装,实时重新加载和交互式调试等功能将工作得更好,所需的配置和调整更少。

    如果您将Dockerfile 移动到根目录,它可以访问两个目录树。然后您可以使用multi-stage build 构建客户端,然后将其复制到服务器中。大概是这样的:

    FROM node:14 AS client
    WORKDIR /app
    COPY client/package.json client/yarn.lock .
    RUN yarn install
    COPY client .
    RUN yarn build
    
    FROM node:14
    WORKDIR /app
    COPY server_api/package.json server_api/yarn.lock .
    RUN yarn install
    COPY server_api .
    COPY --from=client /app/admin/build admin  # <-----
    EXPOSE 5000
    CMD ["node", "index.js"]
    

    在您的代码中,将路径更改为path.resolve(__dirname, 'admin', 'index.html');它应该与COPY --from=client 行的容器文件系统内的目标匹配。

    在您的主机开发环境中,您可以使用符号链接指向文件(在 MacOS 或 Linux 上)

    ln -s ../client/admin/build admin
    

    最后,您需要更改您的 docker-compose.yml 以指向根目录作为构建上下文,并移除绑定挂载(它将有一个悬空符号链接而不是文件内容)。

    server_api:
      build: .
      image: speed_react/server_api
      ports:
        - "5000:5000"
    

    【讨论】:

      猜你喜欢
      • 2018-04-24
      • 1970-01-01
      • 2019-09-05
      • 2020-04-29
      • 2020-05-06
      • 1970-01-01
      • 2017-01-22
      • 2020-04-10
      • 1970-01-01
      相关资源
      最近更新 更多