I am trying my hands on debugging a Nodejs app from inside of Docker using Nodemon.
I can debug my app with Nodemon without Docker using Visual Studio Code's Auto Attach feature.
But when I build my docker image and start the container via npm run dev:docker:debug I get following log but debugger is not attached. It might be something with the volume but I am not able to figure it out...
Successfully built 857d9da57565
Successfully tagged app:dev
Creating docker_app_1 ... done
Attaching to docker_app_1
app_1 |
app_1 | > app#1.0.0 dev:debug /usr/src/app
app_1 | > nodemon --config nodemon.json --env=development
app_1 |
app_1 | [nodemon] 2.0.2
app_1 | [nodemon] to restart at any time, enter `rs`
app_1 | [nodemon] watching dir(s): src/**/*
app_1 | [nodemon] watching extensions: ts
app_1 | [nodemon] starting `cross-env NODE_OPTIONS='--inspect=0.0.0.0:5858' ts-node -r tsconfig-paths/register ./src --env=development`
app_1 | Debugger listening on ws://0.0.0.0:5858/k3h42h4-h49d-4f00-adj877-60f6731548787
app_1 | For help, see: https://nodejs.org/en/docs/inspector
app_1 | Service started at ports:3000
Folder structure
App
|-- docker
| |-- docker-compose.yml
| |-- Dockerfile
| `-- .dockerignore
|-- nodemon.json
|-- package.json
|-- tsconfig.json
|-- tslint.json
`-- src
`-- index.ts
index.ts
import express, { Request, Response } from "express";
const app = express();
const port = process.env.PORT || 3000; // default port to listen
// define a route handler for the default home page
app.get("/", (req: Request, res: Response) => {
res.send("Hello worlds!");
});
// start the Express server
app.listen(port, () => {
console.log(`Service started at ports:${port}`);
});
docker-compose.yml
# docker-compose.yml
version: "3"
services:
app:
image: app:dev
build:
context: ../
dockerfile: ./docker/Dockerfile
ports:
- 3000:3000
volumes:
- ../src:/usr/src/app/src/
Dockerfile
FROM node:12-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . ./
CMD [ "npm", "run", "dev:debug" ]
package.json
{
"name": "app",
"version": "1.0.0",
"description": "API to receive data",
"author": "Nikhil Gupta",
"main": "./dist/index.js",
"scripts": {
"dev:debug": "nodemon --config nodemon.json --env=development",
"dev:docker:debug": "docker-compose -f ./docker/docker-compose.yml up --build"
},
"dependencies": {
"cross-env": "^6.0.3",
"express": "^4.17.1",
"ts-node": "^8.5.4",
"tsconfig-paths": "^3.9.0",
"tslib": "^1.10.0"
},
"devDependencies": {
"#types/express": "^4.17.2",
"#types/node": "^12.12.21",
"nodemon": "^2.0.2",
"tslint": "^5.20.1",
"typescript": "^3.7.4"
}
}
nodemon.json
{
"watch": ["src"],
"ext": "ts",
"ignore": ["src/public"],
"inspect": true,
"exec": "cross-env NODE_OPTIONS='--inspect=0.0.0.0:5858' ts-node -r tsconfig-paths/register ./src"
}
Since the debugger is listening on port 5858 inside the container, you need to bind it to a port on the host machine if you want to connect to it from outside the container similar to how you have done for port 3000 in your compose file.
# docker-compose.yml
version: "3"
services:
app:
image: app:dev
build:
context: ../
dockerfile: ./docker/Dockerfile
ports:
- 3000:3000
- 5858:5858
volumes:
- ../src:/usr/src/app/src/
As mentioned in the comments by #ykit9 I did following
1) Added port 5858 into my docker-compose.yml
# docker-compose.yml
version: "3"
services:
app:
image: app:dev
build:
context: ../
dockerfile: ./docker/Dockerfile
ports:
- 3000:3000
- 5858:5858
volumes:
- ../src:/usr/src/app/src/
2) Added following configuration in VS Code's launch.json file.
{
"type": "node",
"request": "attach",
"name": "Attach to Docker",
"protocol": "auto",
"port": 5858,
"restart": true,
"localRoot": "${workspaceFolder}/src",
"remoteRoot": "/usr/src/app/src"
}
Related
The below code runs the server.js without installing the node modules in the package.json, so it run into an error Error: Cannot find module 'koa'. Is it possible to install node modules on the prebuilt Docker Node image (https://github.com/nodejs/docker-node) using docker-compose?
I tried command: "yarn install && yarn start" in docker-compose.yml, but that's not valid.
docker-compose.yml
version: "3.8"
services:
my-api:
image: node:16-alpine
user: node
working_dir: /home/node/app
volumes:
- ./:/home/node/app
- /home/node/app/node_modules
command: "yarn start"
expose:
- 5000
ports:
- 5000:5000
package.json
{
"name": "my-api",
"private": true,
"scripts": {
"install": "yarn install",
"start": "node server.js"
},
"main": "server.js",
"dependencies": {
"koa": "^2.13.0",
"#koa/cors": "^3.1.0",
"koa-bodyparser": "^4.3.0",
"koa-logger": "^3.2.1",
"koa-router": "^9.0.0"
}
}
server.js
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const logger = require('koa-logger');
const Router = require('koa-router');
const cors = require('#koa/cors');
console.log('server ready');
I got this error in docker desktop in docker containers logs.
I run this command in terminal of vs code
docker compose up
This is the error:
> tracking-system#1.0.0 dev /usr/src/server
> nodemon -r esm -L server.js
[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node -r esm server.js server.js`
[nodemon] app crashed - waiting for file changes before starting...
Error: Cannot find module '/usr/src/server/server.js'
at internal/main/run_main_module.js:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
This is all my files in my project
app (folder)
node_modules (folder)
.dockerignore
.gitignore
Dockerfile
Dockerfile.prod
package.json
package-lock.json
server.js
This is my code:
server.js:
import express from 'express';
import mongoose from 'mongoose';
import cors from 'cors';
import passport from 'passport';
import morgan from 'morgan';
import socketio from 'socket.io';
import http from 'http';
import { success, error } from 'consola';
import { db_connection } from './app/config';
const app = express();
const server = http.createServer(app);
const io = socketio(server);
const PORT = process.env.SERVER_PORT || 8861;
var corsOptions = {
origin: '*',
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
credentials: true,
};
app.use(cors(corsOptions));
app.use(express.json());
app.use(passport.initialize());
app.use(morgan('dev'));
import passport_init from './app/middleware/passport';
import userRoute from './app/routes/user.route';
import authRoute from './app/routes/auth.route';
passport_init(passport);
app.use('/api/users', userRoute);
app.use('/api/auth', authRoute);
const startDatabase = async () => {
try {
await mongoose.connect(db_connection, {
useNewUrlParser: true,
useFindAndModify: true,
useUnifiedTopology: true,
useFindAndModify: false,
dbName: 'tracking-system',
});
success({
message: `Successfully connected with the database on ${db_connection}`,
badge: true,
});
} catch (err) {
error({
message: `Unable to connected with the database ${err}`,
badge: true,
});
setTimeout(startDatabase, 5000);
}
};
startDatabase();
server.listen(PORT, () => {
success({ message: `Server started on PORT ${PORT}`, badge: true });
});
io.on('connection', socket => {
console.log(`Connected: ${socket.id}`)
socket.on('disconnect', () => {
console.log(`Disconnected: ${socket.id}`)
})
socket.on('update-worksheet', function () {
io.sockets.emit('update-landing-page')
})
})
Dockerfile:
FROM node:lts-buster
WORKDIR /project/server
COPY ./server/package*.json ./
RUN npm install
COPY ./.env ../.env
CMD ["npm", "run", "dev"]
package.json:
{
"name": "tracking-system",
"version": "1.0.0",
"description": "for tracking device repairation",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node -r esm server.js",
"dev": "nodemon -r esm -L server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "5.0.1",
"colors": "^1.4.0",
"consola": "^2.15.3",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"esm": "^3.2.25",
"express": "^4.17.1",
"express-session": "^1.17.2",
"http-server": "^0.12.3",
"jsonwebtoken": "^8.5.1",
"moment-timezone": "^0.5.33",
"mongoose": "^5.13.5",
"morgan": "^1.10.0",
"passport": "^0.4.1",
"passport-jwt": "^4.0.0",
"socket.io": "^4.1.3"
},
"devDependencies": {
"nodemon": "^2.0.7"
}
}
Thanks if you can help. My friend can't help.
This is my docker version:
Docker version 20.10.7, build f0df350
This is my docker info:
Client:
Context: default
Debug Mode: false
Plugins:
buildx: Build with BuildKit (Docker Inc., v0.5.1-docker)
compose: Docker Compose (Docker Inc., v2.0.0-beta.6)
scan: Docker Scan (Docker Inc., v0.8.0)
Server:
Containers: 4
Running: 4
Paused: 0
Stopped: 0
Images: 4
Server Version: 20.10.7
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc
Init Binary: docker-init
containerd version: d71fcd7d8303cbf684402823e425e9dd2e99285d
runc version: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 5.10.16.3-microsoft-standard-WSL2
Operating System: Docker Desktop
OSType: linux
Architecture: x86_64
CPUs: 12
Total Memory: 12.43GiB
Name: docker-desktop
ID: LASO:BRSF:IIDP:3W6O:4TRG:CRIF:H54G:WWN3:EFAP:6NLU:MMSS:OHG5
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: No blkio throttle.read_bps_device support
WARNING: No blkio throttle.write_bps_device support
WARNING: No blkio throttle.read_iops_device support
WARNING: No blkio throttle.write_iops_device support
I use windows 10 pro
In the line 3 in your Dockerfile you only copy the package.json of your project but never copy the source code of your app.
FROM node:lts-buster
WORKDIR /project/server
COPY ./server/package*.json ./
RUN npm install
COPY ./.env ../.env
CMD ["npm", "run", "dev"]
So, you can try with this Dockerfile (i changed the workdir and now it copying all source code):
FROM node:lts-buster
WORKDIR /usr/src/server
COPY . .
RUN npm install
CMD ["npm", "run", "dev"]
Reference: Dockerizing a Node.js web app
While creating my node app inside docker I am getting below error
docker container run -it --rm --volume $(pwd):/usr/src/app -p 7007:3000 sample-app-dev:latest
docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused "exec: \"nodemon server.js\": executable f
My Dockerfile looks like below
FROM node:12
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
ENV PATH="/usr/src/app:${PATH}"
ENTRYPOINT ["nodemon server.js"]
Package.json
{
"name": "nodedocker",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"nodemon": "^2.0.4"
}
}
server.js
const express = require( "express" );
const app = express();
const port = 3000;
app.get( "/", ( req, res ) => {
res.send( "Hello World from express JS!!" );
} );
const hobbies = [
"Swimming", "Diving", "Jogging", "Cooking", "Singing" ] ;
app.get("/hobbies", (req, res) => {
res.send(hobbies);
});
const famous_programming = [
"python", "java", "c", "c++", "JS" ] ;
app.get("/famous_programming", (req, res) => {
message = famous_programming.includes("node")? "Yaaay, Node.js" : "Yup! Node.js is a framework from JS" ;
res.send(message);
});
app.listen( port, () => {
console.log( `Node JS started on http://localhost:${port}` )
} );
I am not sure what else I am missing here, any inputs greatly appreciated.
Thank you.
You could configure the package to run nodemon server.js on start, then specify npm start in the entrypoint:
Dockerfile:
FROM node:12
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
ENV PATH="/usr/src/app:${PATH}"
ENTRYPOINT ["npm", "start"]
package.json:
{
"name": "nodedocker",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"nodemon": "^2.0.4"
}
}
Test:
$ docker container run -it --rm q63534772
> nodedocker#1.0.0 start /usr/src/app
> nodemon server.js
[nodemon] 2.0.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node server.js`
Node JS started on http://localhost:3000
Hello I'm trying to make my docker compose work, but I have the following error:
Step 13/15 : COPY .env . COPY failed: stat
/var/lib/docker/tmp/docker-builder209795817/.env: no such file or
directory
I'm not able to find solutions or imagine what I can do to solve this
code:
DockerCompsoe:
version: "3.7"
services:
db:
image: postgres
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: emasa
volumes:
- ./pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
web:
image: emasapg
depends_on:
- dbs
ports:
- "4000:4000"
DockerFile:
FROM node as builder
WORKDIR usr/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node
WORKDIR usr/app
COPY package*.json ./
RUN npm install --production
COPY --from=builder /usr/app/dist ./dist // I GOT PROBLEM HERE
COPY ormconfig.docker.json ./ormconfig.json
COPY .env .
expose 4000
CMD node dist/src/index.js
My package.json:
{
"name": "back-end",
"version": "0.0.1",
"description": "Awesome project developed with TypeORM.",
"scripts": {
"dev:server": "ts-node-dev --respawn --transpileOnly src/index.ts",
"build": "tsc -b"
},
"devDependencies": {
"#types/express": "^4.17.3",
"#types/node": "^13.9.1",
"typescript": "^3.8.3"
},
"dependencies": {
"apollo-server-express": "^2.11.0",
"express": "^4.17.1",
"graphql": "^14.6.0",
"pg": "^7.3.0",
"reflect-metadata": "^0.1.13",
"ts-node": "^8.6.2",
"typeorm": "0.2.24"
}
}
my ormconfig:
{
"type": "postgres",
"host": "db",
"port": 5432,
"username": "postgres",
"password": "postgres",
"database": "emasa",
"synchronize": true,
"logging": false,
"entities": ["src/entity/**/*.ts"],
"migrations": ["src/migration/**/*.ts"],
"subscribers": ["src/subscriber/**/*.ts"],
"cli": {
"entitiesDir": "src/entity",
"migrationsDir": "src/migration",
"subscribersDir": "src/subscriber"
}
}
and this is my folders structures:
The error appears because there is no .env file and no dist folder.
First of all you need to create a .env file at the root of your project structure in order to provide the needed environment variables (e.g. like name, host, port, password and user of your database connection). Next run npm run build to build your project, which will create the dist folder (see your tsconfig.json).
I can't fetch from server container to frontend container even though I am able to get curl response from inside frontend container.
I have a docker-compose set up with a frontend and server container.
I want to fetch server response from frontend, but i get the error GET http://server:5000/api/panels net::ERR_NAME_NOT_RESOLVED. I get the correct response if i execute the following command from inside the frontend container curl http://server:5000/api/panels
Dockerfile server
FROM node:11
ADD . /code
WORKDIR /code
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 5000
CMD [ "node", "server" ]
Dockerfile frontend
FROM node:11
ADD . /frontend
WORKDIR /frontend
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm","start"]
docker-compose.yml
version: '3'
services:
server:
build: .
frontend:
depends_on:
- server
build: ./frontend
ports:
- "3030:3000"
api-call
this.callApi()
.then((res: ISolarPanels) => {
this.setState({ solarPanels: res })
})
.catch((err) => console.warn('server is offline?', err))
private callApi = async () => {
const response = await fetch(process.env.REACT_APP_URL+'/api/panels')
const body = await response.json()\
if (response.status !== 200) {
throw Error(body.message)
}
return body
}
package.json (i use dev script for local development and start for docker
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"#types/d3": "^5.0.1",
"d3": "^5.7.0",
"prettier": "^1.13.5",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-scripts-ts": "2.16.0",
"tslint-eslint-rules": "^5.3.1"
},
"scripts": {
"lint": "node_modules/.bin/tslint -c tslint.json 'src/**/{*.ts,*.tsx}'",
"dev": "REACT_APP_URL=http://localhost:3000 react-scripts-ts start",
"start": "REACT_APP_URL=http://server:5000 react-scripts-ts start",
"build": "react-scripts-ts build",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject"
},
"proxy": "http://localhost:5000/",
"devDependencies": {
"#types/node": "^10.3.3",
"#types/react": "^16.3.17",
"#types/react-dom": "^16.0.6",
"typescript": "^2.9.2"
}
}
For a quick fix, you can allow CORS on your server. here
And in your web application you can use:
0.0.0.0:5000/api for pointing to server.
Also, you would need to bind your port in server service in docker-compose.yml file.
server:
build: .
ports:
- "5000:5000"
To sum up what went wrong and how it was fixed.
The request was of-course sendt from the browser, and not the frontend container, therefore the server port needed to be exposed and CORS enabled from the serverside.