How could I run this dockerized app in development mode? - node.js

The fronted is made with create-react-app and the backend is Node.js with Firebase.
This is my folder structure:
my-app
├── docker-compose.yml
├── client
│ ├── Dockerfile
│ ├── package.json
├── server
│ ├── Dockerfile
│ ├── package.json
docker-compose.yml
version: "3.8"
services:
client:
container_name: client
build: ./client
ports:
- "3000:3000"
tty: true
server:
container_name: server
build: ./server
ports:
- "5000:5000"
client/package.json
{
"name": "react-ui",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.19.2",
"node-sass": "^4.14.1",
"normalize.css": "^8.0.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.1",
"react-scripts": "^3.4.1",
"redux": "^4.0.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://server:5000",
"secure": false
}
client/Dockerfile
FROM node:lts
WORKDIR /client
COPY package*.json /client/
RUN npm install
COPY . /client/
RUN npm run build
EXPOSE 3000
CMD [ "npm", "start" ]
server/package.json
{
"name": "snake-react-node",
"version": "3.0.0",
"engines": {
"node": "10.x"
},
"scripts": {
"start": "node ./build/index.js",
"build": "tsc",
"dev": "nodemon ./src/index.ts"
},
"dependencies": {
"#types/express": "^4.17.7",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"firebase-admin": "^9.0.0",
"moment": "^2.27.0",
"rimraf": "^3.0.2",
"ts-node-dev": "^1.0.0-pre.56",
"typescript": "^3.9.7"
},
"license": "MIT",
"devDependencies": {
"nodemon": "^2.0.4",
"npm-run-all": "^4.1.5"
}
}
server/Dockerfile
FROM node:lts
WORKDIR /server
COPY package*.json /server/
RUN npm install
COPY . /server/
RUN npm run build
EXPOSE 5000
CMD [ "npm", "start" ]
When I run docker-compose up on the root directory, two images and two containers get created, one for each Dockerfile. The app runs flawlessly and a production build is created but I would like to be able to use Docker for development too, with live reloads

Since your server container publishes ports: out, you can change the proxy settings in your package.json file to point at this. In your non-Docker host development environment, set
"proxy": "http://localhost:5000"
and then you can npm run dev to have a totally ordinary local live-reloading development server, targeting your backend service that's running in Docker.
There's not really any technical benefits to trying to simulate a local development environment inside a Docker container, especially for a browser-based application. A typical Webpack-based build toolchain doesn't have complex native dependencies that would require special setup, and since the application itself runs in the browser, it can't take advantage of Docker networking and the container itself doesn't provide any of the application's runtime environment. So the only real difference between running the dev server on the host vs. in a container is which version of Node the Webpack build is using, and hopefully this isn't a substantial difference to your application.

You can use bind volume mounts for dev live reload. Make another dev compose file like docker-compose-dev.yml and add the volumes: section.
Whenever code is changed on the host machine using your favorite IDE, the container will pick it up and do the hot reload.
Note: I haven't tested this setup. Just suggesting something you could do.
#docker-compose-dev.yml
version: "3.8"
services:
client:
container_name: client
build: ./client
volumes:
- ./frontend-src:/client/src
ports:
- "3000:3000"
tty: true
server:
container_name: server
build: ./server
ports:
- "5000:5000"

Related

sqlite3 with docker throws MODULE_NOT_FOUND error

My node application works on my local(MacOS), but it does not work if I use docker.
it works if I try local:
npm install
npm start
It throws error if I try docker
docker-compose build
docker-compose up
I'm getting this error.
Error: Cannot find module '/src/node_modules/sqlite3/lib/binding/napi-v6-linux-musl-x64/node_sqlite3.node'
Package.json
{
"name": "api",
"version": "1.0.0",
"description": "API",
"main": "index.js",
"scripts": {
"test": "rm -rf usersdb.sqlite && jest --forceExit",
"test:coverage": "npm run test -- --coverage --forceExit",
"start": "nodemon app.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.20.1",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"lodash": "^4.17.21",
"mysql": "^2.18.1",
"nodemon": "^2.0.20",
"sqlite3": "^5.1.4"
},
"devDependencies": {
"jest": "^28.1.1",
"supertest": "^6.3.3"
}
}
docker-compose.yml
version: "3.7"
services:
api:
image: test/api
build: ./
command: npm start
restart: on-failure
environment:
SERVER_PORT: 3004
TOKEN_KEY: test123
volumes:
- .:/src
ports:
- "3004:3004"
Dockerfile
FROM node:12.22-alpine as base
WORKDIR /src
COPY package*.json ./
EXPOSE 3004
RUN apk add --no-cache python2 g++ make
RUN npm install
FROM base as dev
ENV NODE_ENV=development
RUN npm install -g nodemon
COPY . ./
CMD ["nodemon", "app.js"]
Delete the volumes: block from your docker-compose.yml.
The volumes: block in your docker-compose.yml file is overwriting your entire application with content from your host system. That includes overwriting the Linux-OS node_modules tree with the MacOS version from your host system.
You don't need this volumes: block. The code and node_modules: tree are built into your image. If you need to develop your application, you can install Node on your host system (on MacOS this might be as little as brew install node) and use that for day-to-day development, even if you're planning to eventually use Docker for final deployment or if you have dependencies that run in containers.

React-Nodejs app frontend does not load with docker-compose up in my network but works in localhost

I have a react nodejs application and it works fine running in local but when I dockerize it and run docker-compose up, only localhost page loads, not for network. I am not sure where my configuration gets wrong for frontend and I would appreciate your help!
I have one dockerfile for frontend(react) and one dockerfile for backend(nodejs). I also have a docker-compose.yml file. The file structure looks like below:
--api(dir for backend)
--dockerfile
--my-app(dir for frontend)
--dockerfile
--dockercompose.yml
My docker file for frontend is as below:
FROM node:10
WORKDIR /my-app
COPY . .
RUN npm install && npm run build
EXPOSE 3000
CMD ["npm", "start"]
My dockerfile for the backend is as below:
FROM node:10
WORKDIR /api
COPY ./package*.json .
RUN npm install
COPY . .
EXPOSE 3080
CMD ["node", "--require", "./tracing.js", "./server.js"]
My docker-compose file is as below:
version: '3'
services:
app-backend:
build: ./api
container_name: app-backend
ports:
- "3080:3080"
app-frontend:
depends_on:
- app-backend
build: ./my-app
container_name: app-frontend
ports:
- "3000:3000"
tty: true
This is how my frontend package.json look like:
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"bootstrap": "^4.5.0",
"react": "^16.13.1",
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": "http://app-backend:3080",
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
In the server.js file in api directory(backend), I have the app listen to port 3080.
port = 3080
app.listen(port, () => {
console.log(`Server listening on the port::${port}`);
});
After docker-compose up, I see
You can now view my-app in the browser.
Local: http://localhost:3000
On Your Network: http://192.168.160.3:3000
Running http://localhost:3000 in browser brings up my app, but http://192.168.160.3:3000 never works and it shows me 'cannot reach the page'. My question is what is this address - 192.168.160.3 ? What are the possible reasons I cannot load http://192.168.160.3:3000?
Another question is does the port 3080 in server.js has to be the same as what is defined in backend dockerfile? It does not seem so, but I don't know why.
You can now view my-app in the browser.
Local: http://localhost:3000
On Your Network: http://192.168.160.3:3000
React's startup script is reporting the LAN IP of the container. This won't be available outside of the Docker network itself and in this case, is a useless piece of information.
If you want to connect via a LAN address, you'll need to use the IP address of the host computer.
does the port 3080 in server.js has to be the same as what is defined in backend dockerfile?
If you're referring to EXPOSE, the answer is "not exactly". EXPOSE is basically documentation and doesn't technically do anything.
What you do need to do is forward to the appropriate container port. So if your server binds to port 3080 in the container, your ports config in compose needs to use
ports:
- "<any available host port>:3080"
This is only required if you want to access the server directly from the host. Since you're proxying requests from the React dev server within the Docker network, you don't really need it at all.

docker-compose cant run react without node_modules already existing

Im using docker/docker-compose to get my react (ts) app up and running.
The script im currently using works perfectly, on 1 condition. That I've already did 'npm install' inside the directory, while not in docker.
I would like to be able to clone my project from github, and just do docker-compose up, and that it works than.
Right now i first have to run 'npm install', and than 'docker-compose up' for it to work sadly.
I tried just using RUN npm install react-scripts -g, and that kinda works. however i than get a error for typescript, and all other packages.
What I want to be happening is. When I clone my repo, and use docker-compose up. That my whole project runs. It also should make a node_modules folder in my react folder that I can see in my IDE. This is so that my IDE knows the code in the package and doesn't yell at me the whole time.
I cant figure out how to get this to work, I'm already struggling on this for hours and can't find online how to fix it. Hope anyone can help me :D
My structure looks something like this:
apps
frontend
Dockerfile
composer.json
// All the other react files/folders
docker-compose.yml
Dockerfile:
FROM node:16.14.2
WORKDIR /usr/src/app
COPY ./package*.json ./
RUN npm install
CMD npm start --host 0.0.0.0 --port 3000 --disableHostCheck true
docker-compose.yml:
version: '3'
services:
frontend:
build:
context: ./apps/frontend
dockerfile: ./Dockerfile
volumes:
- ./apps/frontend:/usr/src/app
ports:
- 3000:3000
environment:
- CHOKIDAR_USEPOLLING=true
- API_BASE_URL=host.docker.internal:8080/api
extra_hosts:
- "host.docker.internal:host-gateway"
The error im getting is:
frontend_1 | > spa#0.1.0 start
frontend_1 | > react-scripts start "0.0.0.0" "3000"
frontend_1 |
frontend_1 | sh: 1: react-scripts: not found
cyldiscordbot_frontend_1 exited with code 127
package.json (idk if you need it, but here it is):
{
"name": "spa",
"version": "0.1.0",
"private": true,
"dependencies": {
"#cylbot/cyldiscordbotlanguage": "^2.0.3",
"#emotion/core": "^11.0.0",
"#emotion/react": "^11.7.1",
"#emotion/styled": "^11.6.0",
"#mui/icons-material": "^5.3.1",
"#mui/material": "^5.5.0",
"#testing-library/user-event": "^13.2.1",
"#types/node": "^17.0.9",
"#types/react": "^17.0.38",
"#types/react-dom": "^17.0.11",
"axios": "^0.25.0",
"emotion-theming": "^11.0.0",
"enzyme": "^3.11.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.6",
"react-router-dom": "^6.2.1",
"react-scripts": "5.0.0",
"redux": "^4.1.2",
"redux-saga": "^1.1.3",
"redux-thunk": "^2.4.1",
"styled-components": "^5.3.3",
"typescript": "^4.5.4",
"web-vitals": "^2.1.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -s public"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
],
"overrides": [
{
"files": [
"**/*.stories.*"
],
"rules": {
"import/no-anonymous-default-export": "off"
}
}
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"#material-ui/core": "^4.12.3",
"#storybook/addon-actions": "^6.4.19",
"#storybook/addon-essentials": "^6.4.19",
"#storybook/addon-interactions": "^6.4.19",
"#storybook/addon-links": "^6.4.19",
"#storybook/builder-webpack5": "^6.4.19",
"#storybook/manager-webpack5": "^6.4.19",
"#storybook/node-logger": "^6.4.19",
"#storybook/preset-create-react-app": "^4.0.1",
"#storybook/react": "^6.4.19",
"#storybook/testing-library": "^0.0.9",
"#testing-library/jest-dom": "^5.16.2",
"#testing-library/react": "^12.1.4",
"#testing-library/react-hooks": "^7.0.2",
"#types/jest": "^27.4.1",
"#types/styled-components": "^5.1.20",
"jest": "^27.5.1",
"react-test-renderer": "^17.0.2",
"ts-jest": "^27.1.3",
"webpack": "^5.70.0"
}
}
I can give out a lot of info about this project, so if more info is required just ask! :D
I figured it out. I asked a friend, and he helped me out.
I needed to change my Dockerfile to:
FROM node:16.14.2
WORKDIR /usr/src/app
RUN npm install -g react-scripts
RUN chown -Rh node:node /usr/src/app
USER node
EXPOSE 3000
CMD [ "sh", "-c", "npm install && npm run start" ]
Your Dockerfile is missing the application code; it only copies the package.json file in. This gives you an incomplete image that you can't just run. You're missing a line:
COPY ./ ./
I'd put this after the RUN npm install line, to make rebuilding the image faster.
Since your image is incomplete, in your current setup you have to inject the code from the host, and that hides the node_modules directory that the image builds. That's why you also have to run npm install on the host. If you COPY the application code into the image, you don't need the volumes: block.
version: '3.8'
services:
frontend:
build: ./apps/frontend # short form with default dockerfile:
ports:
- 3000:3000
environment:
- API_BASE_URL=host.docker.internal:8080/api
extra_hosts:
- "host.docker.internal:host-gateway"
# no volumes: or polling environment variable

Can't Dockerize my simple typescript website

I am trying to get a Typescript project running in Docker. I created the Docker file based on a tutorial but when I run it I get:
/usr/local/bin/docker-entrypoint.sh: 8: exec: .: Permission denied
I am not sure how to diagnosis this problem.
I can enter the container with
docker run --rm -it d3ca97c88aec bash -il
and run the server with
npm start
I have no file called docker-entrypoint.sh and I didn't make one.
I STRONGLY FEEL THIS IS BECAUSE TYPESCRIPT MAKES A BUILD FOLDER AND THAT BUILD FOLDER IS PERMISSIONED DIFFERENTLY.
Dockerfile
FROM node:12
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm#5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
# Bundle app source
COPY . .
ENV COUCH_URL=NotSafeForStackOverflow
RUN npx tsc
EXPOSE 8080
CMD npx ts-node index.ts
{
"name": "express-react-app",
"version": "1.0.0",
"main": "index.js",
"repository": "",
"author": "",
"license": "",
"private": null,
"dependencies": {
"agentkeepalive": "^4.1.3",
"apollo-utilities": "^1.3.4",
"base64-arraybuffer": "^0.2.0",
"express": "^4.17.1",
"express-graphql": "^0.11.0",
"graphql": "^15.3.0",
"graphql-depth-limit": "^1.1.0",
"graphql-tag": "^2.11.0",
"graphql-type-json": "^0.3.2",
"i": "^0.3.6",
"merge-graphql-schemas": "^1.7.8",
"nano": "^8.2.2",
"node-webcrypto-ossl": "^2.1.1",
"npm": "^6.14.8",
"text-encoding": "^0.7.0",
"ts-node": "^9.0.0",
"typescript": "^3.7.4",
"uuid": "^8.3.0"
},
"scripts": {
"start": "npx ts-node index.ts",
"build": "npx tsc",
"dev": "nodemon --watch '**/*.ts' --exec 'ts-node' index.ts"
},
"devDependencies": {
"#types/express": "^4.17.7",
"#types/graphql": "^14.5.0",
"#types/node": "^14.6.3"
}
}
when you run CMD npx ts-node index.ts
it will overwrite default CMD [ "node" ]
please refer link below to how to use node image :
https://github.com/nodejs/docker-node/blob/master/README.md#how-to-use-this-image
you shoud be able done by using docker-compose :
version: "2"
services:
node:
image: "node:8"
user: "node"
working_dir: /home/node/app
environment:
- NODE_ENV=production
volumes:
- ./:/home/node/app
expose:
- "8081"
command: "npm start"

Docker compose volumes in nodejs microservices application

When make volumes in docker-compose.yml and run docker-compose up and in "yarn run" step, it says (error Couldn't find a package.json file in "/usr/src/app")
my Dockerfile
FROM node:12
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json .
COPY yarn.lock .
RUN yarn
COPY . .
CMD [ "yarn", "watch" ]
docker-compose.yml
version: "3"
services:
listings-service:
build: ./listings-service
volumes:
- ./listings-service:/usr/src/app
package.json
{
"name": "listings-service",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"watch": "babel-watch -L ./index.js"
},
"devDependencies": {
"babel-watch": "^7.0.0",
"nodemon": "^2.0.2"
},
"dependencies": {
"#babel/core": "^7.9.0",
"#babel/polyfill": "^7.8.7",
"#babel/preset-env": "^7.9.0",
"babel-plugin-module-resolver": "^4.0.0",
"core-js": "3"
}
}
why do you need the volume here? your docker files compy all the files in and place them inside the docker image. In addition, running yarn will install dependencies and place them in /usr/src/app.
Adding the volume on the docker-compose ==> all files from the docker image will be removed and placed with the files inside the local path ./listings-service

Resources