Running react and node in a single port using Dockerfile - node.js

I am trying to run docker for my sample project where in the container I need a single port to run, But the build of react code will serve as the index.html, I have the below folder structure.
In index.js file I have tried to add the static path, What am I doing wrong here? I have commented it..
I have tried this much.
sampleapp
client
// using cra (create react app) files
src
public
...
server
index.js
Dockerfile
// app.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
state = {
response: null
}
componentWillMount(){
this.dataFetching()
}
dataFetching = async () => {
const resjson = await fetch('/api/data');
const res = await resjson.json();
this.setState({
response: res.data
})
}
render() {
return (
this.state.response ? this.state.response : null
);
}
}
export default App;
// package.json --client
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.8.3",
"react-dom": "^16.8.3",
"react-scripts": "2.1.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"proxy": "http://localhost:4000"
}
// index.js -- server
const express = require('express');
const path = require('path');
const app = express();
// app.use(express.static(path.join(__dirname, 'build')));
// app.get('/*', function(req, res) {
// res.sendFile(path.join(__dirname, '..', 'app', 'build', 'index.html'));
// });
app.get('/api/data', (req, res) => {
res.send({data: "Success"})
})
app.listen(4000);
// Dockerfile - sampleapp
FROM node:10.15.1-alpine
COPY . /var/app
WORKDIR /var/app/client
RUN npm install --no-cache && npm run build && npm install -g serve
WORKDIR /var/app/server
RUN npm install --no-cache
EXPOSE 4000
EXPOSE 3000

For the Dockerfile you can change it to the following:
FROM node:10.15.1-alpine
COPY . /var/app
WORKDIR /var/app/client
RUN npm install --no-cache && npm run build && npm install -g serve
WORKDIR /var/app/server
RUN npm install --no-cache
EXPOSE 4000
CMD [ "npm", "start", "index.js" ]
For index.js (server), you can change it to the following:
const express = require('express');
const path = require('path');
const app = express();
app.get('/api/data', (req, res) => {
res.send({data: "Success"})
})
app.use(express.static(path.join(__dirname, '..', 'client', 'build')));
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, '..', 'client', 'build', 'index.html'));
});
app.listen(4000, '0.0.0.0');
React will be served as a static file through nodeJS
index.js needs to be binded to 0.0.0.0 so you can connect to it from outside the container.

Related

Node.js not responding to API calls with my app? Working perfectly during development environment, however not when hosted

Trying to make my first Vue application, simple game with MEVN stack. Working perfect interacting with backend on development environment, however when hosting it doesn't fetch the data from the server.
Anyone able to point out what I have incorrect with the below?
More info below:
File structure:
/root
 |- config.js
 |- server.js
 |- package.json + package-lock.json
 |- client/
  |- vue.config.json
  |- ... (rest of dist, src, node_modules, public etc.)
 |- models/
  |- Elf.js + HighScore.js
 |- routes/
  |- api/
   |- elf.js + highScore.js
config.js
module.exports = {
hostUrl: process.env.HOST_URL,
mongoURI: process.env.MONGO_URI,
PORT: process.env.PORT || 3000,
};
server.js
const express = require("express");
const app = express();
const port = 3000;
const mongoose = require("mongoose");
const { PORT, mongoURI } = require("./config.js");
// routes
const Player = require("./routes/api/player");
const Elf = require("./routes/api/elf");
const HighScore = require("./routes/api/highScore");
// cors is a middleware that allows us to make requests from our frontend to our backend
const cors = require("cors");
// morgan is a middleware that logs all requests to the console
const morgan = require("morgan");
// body-parser is a middleware that allows us to access the body of a request
const bodyParser = require("body-parser");
const path = require("path");
app.use(cors());
// use tiny to log only the request method and the status code
app.use(morgan("tiny"));
app.use(bodyParser.json());
// chek if we are in production
if (process.env.NODE_ENV === "production") {
// check if we are in production mode
app.use(express.static("client/dist"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "dist", "index.html"));
});
}
// test if server is running and connected to mongoDB
app.get("/", (req, res) => {
res.send("Hello World!");
});
// app.get("/", (req, res) => {
// res.send("Hello World!");
// });
// use routes
app.use("/api/", Player);
app.use("/api/", Elf);
app.use("/api/", HighScore);
mongoose
.connect(mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useUnifiedTopology: true,
})
.then(() => console.log("MongoDB connected..."))
.then(() => {
// log uri to console
console.log(`MongoDB connected to ${mongoURI}`);
})
.catch((err) => console.log(err));
app.listen(PORT, () => {
console.log(`Example app listening at ${PORT}`);
});
package.json
{
"name": "week1",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"server": "nodemon server.js --ignore 'client/'",
"client": "npm run serve --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\"",
"start": "node server.js",
"build": "npm install --prefix client && npm run build --prefix client"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.1",
"bootstrap": "^5.2.3",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"mongoose": "^6.7.5",
"morgan": "^1.10.0",
"portal-vue": "^2.1.7"
},
"devDependencies": {
"concurrently": "^7.6.0",
"nodemon": "^2.0.20"
}
}
Running within my dev environment at root dir using 'npm run dev', the app works flawlessly send/ receive data from mongoDB during this time. This starts up http://localhost:8080/. Also tried install of 'npm install -g serve' and running 'serve -s dist', this starts up serving at localhost:36797 and working flawlessly too.
I have tried to setup on Vercel & Render, both giving me the same issue where I'm not getting much feedback and the data isn't being fetched. Anyone else has this issue before?

Having modules problems Dockerizng simple node app

Having some problems while trying to create my first node.js app , super new to JS..
Trying to dockerize the app , like so :
docker build -t echo_app .
docker run -p 3000:3000 echo_app
End goal is to echo user input , like so :
http://example/?name=Eyal -> Hello Eyal
http://example/ -> Hello World
ERROR IM GETTING
Error: Cannot find module 'express'
Require stack:
- /app/index.js
.
.
code: 'MODULE_NOT_FOUND',
requireStack: [ '/app/index.js' ]
}
Directroy containes :
index.js
const express = require('express')
const log4js = require('log4js')
const app = express()
const logger = log4js.getLogger()
const echo = (req, res) => {
logger.debug("Request: ", req)
const input = 'name' in req.query ? req.query.input : ''
if (input.length == 0) {
res.send('Echo World')
} else {
res.send(`Echo ${input}`)
}
}
app.get('/', (req, res) => echo(req, res))
Dockerfile
FROM mhart/alpine-node:12
WORKDIR /app
ADD . ./
ENTRYPOINT ["node", "/app/index.js"]
package.json
{
"name": "echo",
"version": "1.0.0",
"description": "You talk, we talk back!",
"main": "index.js",
"author": "eyal",
"license": "MIT",
"dependencies": {
"express": "^4.17.1",
"js-yaml": "^3.13.1",
"log4js": "^5.2.2",
"saslprep": "^1.0.3"
}
}
To get it up and running, you first need to install the node dependencies by adding npm install to your Dockerfile, like this
FROM mhart/alpine-node:12
WORKDIR /app
ADD . ./
RUN npm install
ENTRYPOINT ["node", "/app/index.js"]
Then you need to have your Node app listen for requests by adding
app.listen(3000, () => {
console.log(`Example app listening at http://localhost:3000`)
})
at the bottom of index.js.
Finally, a small error in your code. req.query.input needs to be req.query.name.
That should hopefully get you going.

how to run React + express + node on nginx ec2

Everything works fine on local machine, Please let me if my server setup is correct
Project Structure
/client/--React frontend app
/client/package.json
/index.js
/package.json -- express server
In My /index.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const path = require("path");
const app = express();
app.use(cors());
app.use(express.json());
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
app.listen(process.env.B_PORT || 5000, () => {
console.log(`Express server Up and Running - Port : ${process.env.B_PORT}`);
});
In My /client/package.json
{
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:5000",
}
I am getting 405 not allow for post request, but when i do http://myec2ip:5000 i can json response from express.
What config am i missing ?
You will need to open port 5000 in security group setting of ec2 and allow anyone to access it using 0.0.0.0 for incoming connections.

How to Setup Proxy Target in React Native with Nodejs?

Trying to configure proxy in react native with node to run axios calls.
Tried the following code in server/package.json
"proxy": {
"/*": {
"target": "http://localhost:5000/"
}
},
"scripts": {
"start": "node index.js",
"server": "nodemon index.js",
"client": "cd ../client && yarn ios",
"dev": "concurrently \"yarn server\" \"yarn client\""
}
server/authRouter.js
const authRouter = require('express').Router();
authRouter.get('/test', (req, res) => {
res.send('proxy success');
});
module.exports = authRouter;
server/index.js
const express = require('express');
const authRouter = require('./authRouter');
const app = express();
app.use('/auth', authRouter);
const PORT = process.env.PORT || 5000;
app.listen(PORT);
client/app.js
await axios.get('/auth/test');
When I run yarn dev and test an axios call, it logs the following error
LOG [Error: Network Error]
any help would be much appreciated.
Try calling the proxy directly in axios
http://localhost:5000/auth/test
I'm not sure why it doesn't work that way, even i had a problem in the past.

React content not found heroku deployment

Im trying to deploy a nodejs and react app to Heroku. It works completely fine local and it does serve my backend, but i get Not Found on anything else than my api endpoints. It seems like its not running the build script in the client folder. Can anyone help me spot where it goes wrong?
server.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const path = require('path');
const projects = require('./routes/api/projects');
const app = express();
// Body parser middlewaree
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// DB Config
const db = require('./config/keys').mongoURI;
// Connect to DB
mongoose
.connect(
db,
{ useNewUrlParser: true }
)
.then(() => console.log('mongoDB connected.'))
.catch(err => console.log(err));
// Setting up routes
app.use('/api/projects', projects);
// Serve static assets if in production
app.use(express.static(path.join(__dirname, '/client/build')));
app.get('*', (req, res) => {
res.sendfile(path.join((__dirname, '/client/build/index.html')));
});
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server up and running on ${port}`));
package.json
"scripts": {
"client-install": "npm install --prefix client",
"start": "node server.js",
"server": "nodemon server.js",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\"",
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client"
},
I've deployed successfully to Heroku using the following code (I've just answered an alike question here):
app.use(express.static(path.join(__dirname, './client/build')))
app.get('*', function(_, res) {
res.sendFile(path.join(__dirname, './client/build/index.html'), function(err) {
if (err) {
res.status(500).send(err)
}
})
})
Also, if you're trying to deploy a create-react-app application, you can use this buildpack. Buildpacks are scripts that are run when your app is deployed. They are used to install dependencies for your app and configure your environment.
You can see the full code here of how I usually deploy Heroku applications.

Resources