我正在开始一个新项目。我目前在根文件夹中有这样的结构:
/app (CRA frontend app)
/server (Node.js Express app)
Dockerfile
docker-compose.yml
我的要求如下:
发展
生产
我现在所在的位置介于一切之间。我不知道如何以正确的方式设置Docker才能使整个工作正常进行,我也不知道在开发时如何构建React应用程序与Express应用程序的结构。一旦我知道如何构造开发部分... + Nginx作为Express应用程序的代理,生产部分似乎会变得更容易。
我目前正在构建一个Docker容器,该容器会在可以进行热重装的情况下启动一个容器,但我不知道如何设置Express部件,以便它们可以很好地协同工作...?
非常感谢您的帮助。
谢谢
答案 0 :(得分:1)
非常广泛的问题。将其分解为更直接的问题也许更好。无论如何,我认为在Docker中运行您的开发设置并不理想。而是通常使用CRA构建您的应用。然后在Docker中部署。
在我自己的项目中,我有一个运行节点服务器的docker容器,该节点服务器使用SSR为react app提供服务。
这是码头工人部分。请注意,您的package.json
应该有一个名为start:prod
的脚本才能起作用。然后,该脚本将在生产中启动您的应用程序。
// --- Dockerfile
# Pulled from docker hub and has everything
# needed to run a node project
FROM node:alpine
ENV PORT 3000
# Navigate (cd) to the app folder in the docker container
WORKDIR /usr/src/app
# Copy all package.json / package-lock.json etc. to the root folder
# Executed on build: docker build .
COPY ./package*.json ./
RUN npm i
# copy entire project into docker container
COPY . .
# build front-end with react build scripts and store them in the build folder
RUN npm run build
EXPOSE 3000
CMD ["npm", "run", "start:prod"]
这是将启动服务器的快递服务器。
// -- server.js
import express from "express";
import router from "./controller/index";
const app = express();
const port = 4000;
// Tell the app to use the routes above
app.use(router);
// start the app
app.listen(port, () => {
console.log(`express running on port ${port}`);
});
这是您需要启动的controller/index.js
文件
// -- controller/index.js
import express from "express";
import path from "path";
import serverRenderer from '../middleware/renderer';
const router = express.Router();
// root (/) should always serve our server rendered page
router.use('^/$', serverRenderer());
// other static resources should just be served as they are
router.use(express.static(
path.resolve(__dirname, '..', '..', 'build'),
{ maxAge: '30d' },
));
export default router;
最后是在服务器上渲染应用程序的渲染器。
// -- renderer.js
import React from "react";
import { renderToString } from "react-dom/server";
import App from "../../src/App";
const path = require("path");
const fs = require("fs");
export default () => (req, res) => {
// point to html file created by CRA's build tool
const filePath = path.resolve(__dirname, "..", "..", "build", "index.html");
fs.readFile(filePath, "utf8", (error, htmlData) => {
if (error) {
console.error("error", error);
return response.status(404).end();
}
// render the app as string
const html = renderToString(<App />);
// inject rendered app into final html and send
return res.send(
htmlData
.replace('<div id="root"></div>', `<div id="root">${html}</div>`)
);
})
}
您将需要bootstrap.js
注入对某些软件包的支持。
// -- bootstrap.js
require('ignore-styles');
require('url-loader');
require('file-loader');
require('babel-register')({
ignore: [/(node_modules)/],
presets: ['es2015', 'react-app'],
plugins: [
'syntax-dynamic-import',
'dynamic-import-node'
]
});
require("./index");
您可以在这里找到所有详细信息: https://blog.mytoori.com/react-served-by-express-running-in-docker-container