Cannot find module '/usr/src/app/server.js'

5/11/2020

I have tested the app using minikube locally and it works. When I use the same Doeckerfile with deploymnt.yml, the pod returns to Error state with the below reason

Error: Cannot find module '/usr/src/app/server.js'

Dockerfile:

FROM node:13-alpine
WORKDIR /api
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Deployment.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-app-dep
  labels:
    app: nodejs-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nodejs-app
  template:
    metadata:
      labels:
        app: nodejs-app
    spec:
      serviceAccountName: opp-sa
      imagePullSecrets:
        - name: xxx
      containers:
      - name: nodejs-app
        image: registry.xxxx.net/k8s_app
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 3000

Assuming it could be a problem with "node_modules", I had "ls" on the WORDIR inside the Dockerfile and it does show me "node_modules". Does anyone what else to check to resolve this issue ?

-- techPM
kubernetes

2 Answers

5/14/2020
  • Since I can't give you this level of suggestions on a comment I'm writing you a fully working example so you can compare to yours and check if there is something different.

Sources:

  • Your Dockerfile:
FROM node:13-alpine
WORKDIR /api
COPY package*.json .
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "node", "server.js" ]
  • Sample package.json:
{
  "name": "docker_web_app",
  "version": "1.0.0",
  "description": "Node.js on Docker",
  "author": "First Last <first.last@example.com>",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.16.1"
  }
}
  • sample server.js:
'use strict';

const express = require('express');

// Constants
const PORT = 8080;
const HOST = '0.0.0.0';

// App
const app = express();
app.get('/', (req, res) => {
  res.send('Hello World');
});

app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
  • Build image:
$ ls
Dockerfile  package.json  server.js

$ docker build -t k8s_app .
...
Successfully built 2dfbfe9f6a2f
Successfully tagged k8s_app:latest

$ docker images k8s_app
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
k8s_app             latest              2dfbfe9f6a2f        4 minutes ago       118MB
  • Your deployment sample + service for easy access (called nodejs-app.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-app-dep
  labels:
    app: nodejs-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nodejs-app
  template:
    metadata:
      labels:
        app: nodejs-app
    spec:
      containers:
      - name: web-app
        image: k8s_app
        imagePullPolicy: Never
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: web-app-svc
spec:
  type: NodePort
  selector:
    app: nodejs-app
  ports:
    - port: 8080
      targetPort: 8080

Note: I'm using the minikube docker registry for this example, that's why imagePullPolicy: Never is set.


  • Now I'll deploy it:
$ kubectl apply -f nodejs-app.yaml 
deployment.apps/nodejs-app-dep created
service/web-app-svc created
$ kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
nodejs-app-dep-5d75f54c7d-mfw8x   1/1     Running   0          3s
  • Whenever you need to troubleshoot inside a pod you can use kubectl exec -it <pod_name> -- /bin/sh (or /bin/bash depending on the base image.)
$ kubectl exec -it nodejs-app-dep-5d75f54c7d-mfw8x -- /bin/sh
/api # ls
Dockerfile         node_modules       package-lock.json  package.json       server.js

The pod is running and the files are in the WORKDIR folder as stated in the Dockerfile.

  • Finally let's test accessing from outside the cluster:
$ minikube service list
|-------------|-------------|--------------|-------------------------|
|  NAMESPACE  |    NAME     | TARGET PORT  |           URL           |
|-------------|-------------|--------------|-------------------------|
| default     | web-app-svc |         8080 | http://172.17.0.2:31446 |
|-------------|-------------|--------------|-------------------------|

$ curl -i http://172.17.0.2:31446
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 11
ETag: W/"b-Ck1VqNd45QIvq3AZd8XYQLvEhtA"
Date: Thu, 14 May 2020 18:49:40 GMT
Connection: keep-alive

Hello World$

The Hello World is being served as desired.

To Summarize:

  1. I Build the Docker Image in minikube ssh so it is cached.
  2. Created the manifest containing the deployment pointing to the image, added the service part to allow access externally using Nodeport.
  3. NodePort routes all traffic to the Minikube IP in the port assigned to the service (i.e:31446) and deliver to the pods matching the selector listening on port 8080.

A few pointers for troubleshooting:

  • kubectl describe pod <pod_name>: provides precious information when the pod status is in any kind of error.
  • kubectl exec is great to troubleshoot inside the container as it's running, it's pretty similar to docker run command.
  • Review your code files to ensure there is no baked path in it.
  • Try using WORKDIR /usr/src/app instead of /api and see if you get a different result.
  • Try using a .dockerignore file with node_modules on it's content.

Try out and let me know in the comments if you need further help

-- willrof
Source: StackOverflow

5/16/2020

@willrof, thanks for the detailed write-up. A reply to your response is limited to 30 characters and hence I'm posting as new comment.

My problem was resolved yesterday. It was with COPY . .

It works perfectly fine in my local but, when I tried to deploy onto the cluster with the same Dockerfile, I was running into the issue of "cannot find module..."

So it finally worked when the directory path was mentioned instead of . . while copying files

COPY /api /usr/app         #copy project basically
WORKDIR /usr/app           #set workdir just before npm install
RUN npm install
EXPOSE 3000

Moving WORKDIR statement before installing "node_modules" worked in my case. I'm surprised to figure this as the problem though it worked locally with COPY . .

-- techPM
Source: StackOverflow