Unable to resolve sequelize package in /usr/src/app of the api server container?

7/23/2019

I am basically trying to run an react js app which is mainly composed of 3 services namely postgres db, API server and UI frontend(served using nginx).Currently the app works as expected in the development mode using docker-compose but when i tried to run this in the production using kubernetes,I was not able to access the api server of the app(CONNECTION REFUSED).

I already tried running the command npm install within the api server container.

Dockerfile for API server image

FROM node:12.4.0-alpine
RUN mkdir -p usr/src/app
WORKDIR /usr/src/app
COPY package.json package.json
RUN npm install sequelize-cli nodemon -g
RUN npm install && npm cache clean --force
WORKDIR /usr/src/app
COPY . .
WORKDIR /usr/src/app
EXPOSE 8000
CMD [ "npm","start" ]

package.json of API server

{
  "name": "wootz-backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node_modules/.bin/nodemon index.js",
    "migrate": "node_modules/.bin/sequelize db:migrate --config config/config.json"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "nodemon": "^1.19.1",
    "pg": "^7.11.0",
    "sequelize": "^5.8.7",
    "sequelize-cli": "^5.4.0"
  }
}

API persistant volume one yaml

kind: PersistentVolume
apiVersion: v1
metadata:
  name: api-initdb-pv-volume
  labels:
    type: local
    app: api
spec:
  storageClassName: manual
  capacity:
    storage: 1Mi
  accessModes:
    - ReadOnlyMany
  hostPath:
    path: "/home/vignesh/page designer kubernetes yamls/api"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: api-initdb-pv-claim-one
  labels:
    app: api
spec:
  storageClassName: manual
  accessModes:
    - ReadOnlyMany
  resources:
    requests:
      storage: 1Mi

API persistant volume two yaml

kind: PersistentVolume
apiVersion: v1
metadata:
  name: api-initdb-pv-volume-2
  labels:
    type: local
    app: api
spec:
  storageClassName: manual
  capacity:
    storage: 1Mi
  accessModes:
    - ReadOnlyMany
  hostPath:
    path: "/home/vignesh/page designer kubernetes yamls/api"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: api-initdb-pv-claim-two
  labels:
    app: api
spec:
  storageClassName: manual
  accessModes:
    - ReadOnlyMany
  resources:
    requests:
      storage: 1Mi

APIserver.yaml

apiVersion: v1
kind: Service
metadata:
  name: apiserver
  labels:
    app: apiserver
spec:

  ports:
  - name: apiport
    port: 8000
    targetPort: 8000

  selector:
    app: apiserver
    tier: backend

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apiserver
  labels:
    app: apiserver
spec:
  selector:
    matchLabels:
      app: apiserver
      tier: backend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: apiserver
        tier: backend
    spec:

      containers:
      - image: suji165475/vignesh:apifinal
        name: apiserver
        env:
        - name: POSTGRES_PASSWORD
          value: password
        - name: POSTGRES_USER
          value: postgres
        - name: POSTGRES_DB
          value: wootz
        ports:
        - containerPort: 8000
          name: myport
        volumeMounts:
        - name: api-persistent-storage-one
          mountPath: /usr/src/app
        - name: api-persistent-storage-two
          mountPath: /usr/src/app/node_modules
      volumes:
      - name: api-persistent-storage-one
        persistentVolumeClaim:
          claimName: api-initdb-pv-claim-one
      - name: api-persistent-storage-two
        persistentVolumeClaim:
          claimName: api-initdb-pv-claim-two

When I tried to run the command npm run migrate inside the api server container I got an error saying-

/usr/src/app # npm run migrate

wootz-backend@1.0.0 migrate /usr/src/app sequelize db:migrate --config config/config.json

Unable to resolve sequelize package in /usr/src/app ERR! code ELIFECYCLE ERR! errno 1 ERR! wootz-backend@1.0.0 migrate: sequelize db:migrate --config > config/config.json ERR! Exit status 1 ERR! ERR! Failed at the wootz-backend@1.0.0 migrate script.

I also tried running the command npm install --save sequelize in the api container but this time I got a different error saying-

WARN checkPermissions Missing write access to /usr/src/app/node_modules/pg WARN pg-pool@2.0.6 requires a peer of pg@>5.0 but none is installed. You must > install peer dependencies yourself. WARN wootz-backend@1.0.0 No description WARN wootz-backend@1.0.0 No repository field.

ERR! path /usr/src/app/node_modules/pg ERR! code ENOENT ERR! errno -2 ERR! syscall access ERR! enoent ENOENT: no such file or directory, access > > '/usr/src/app/node_modules/pg' ERR! enoent This is related to npm not being able to find a file. ERR! enoent

NOTE: This problem happens only when I run it using kubernetes and not in development mode using docker-compose.Therefore it can't be a problem with the app itself.

-- Vignesh Swaminathan
docker
kubernetes
node.js
npm
reactjs

1 Answer

7/23/2019

Your application should be built into the Docker image you’re deploying.

There’s a “pattern” of mounting your local source code on top of the Docker image to do local development. This pattern just does not work in Kubernetes. You cannot do “live” development on a deployed Kubernetes pod.

Fortunately, fixing this cuts down your Kubernetes YAML by about two thirds. You need to just outright delete both PersistentVolumes and PersistentVolumeClaims, and the volumes: and volumeMounts: in the deployment spec.

When you make changes to your application, you need to docker build a new image and somehow cause the deployment to restart. The “best” way is to use a different image tag and change the tag in the deployment object, which will cause it to do a rolling restart of pods, and can be cleanly rolled back to the old image if there’s a critical problem with the new code.

(There are two technical problems with this pattern in Kubernetes. The first is that you don’t directly control which node a pod will run on, so you have to manually copy your source code on to every node; that very much misses the point of Kubernetes. The second is that a plain docker run will populate an empty volume mounted over an image path with the content from the image, but Kubernetes will not, so the “trick” of using an anonymous volume to use the node_modules tree from the image [now it contains Very Important Application Data and Docker will never update it again] doesn’t actually work; you’ll just get empty node_modules.)

-- David Maze
Source: StackOverflow