<p>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). </p>

<p>I already tried running the command npm install within the api server container.</p>

<p>Dockerfile for API server image</p>

<pre><code>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 &amp;&amp; npm cache clean --force
WORKDIR /usr/src/app
COPY . .
WORKDIR /usr/src/app
EXPOSE 8000
CMD [ "npm","start" ]

</code></pre>

<p>package.json of API server</p>

<pre><code>{
  "name": "wootz-backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" &amp;&amp; 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"
  }
}
</code></pre>

<p>API persistant volume one yaml</p>

<pre><code>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
</code></pre>

<p>API persistant volume two yaml</p>

<pre><code>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

</code></pre>

<p>APIserver.yaml</p>

<pre><code>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
</code></pre>

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

<blockquote>
  <p>/usr/src/app # npm run migrate</p>
  
  <p>wootz-backend@1.0.0 migrate /usr/src/app
  sequelize db:migrate --config config/config.json</p>
  
  <p>Unable to resolve sequelize package in /usr/src/app
   ERR! code ELIFECYCLE
   ERR! errno 1
   ERR! wootz-backend@1.0.0 migrate: <code>sequelize db:migrate --config &gt; config/config.json</code>
   ERR! Exit status 1
   ERR!
   ERR! Failed at the wootz-backend@1.0.0 migrate script.</p>
</blockquote>

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

<blockquote>
  <p>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.</p>
  
  <p>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</p>
</blockquote>

<p>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.</p>

Vignesh Swaminathan
<p>Your application should be built into the Docker image you’re deploying.</p>

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

<p>Fortunately, fixing this cuts down your Kubernetes YAML by about two thirds.  You need to just outright delete both <code>PersistentVolume</code>s and <code>PersistentVolumeClaim</code>s, and the <code>volumes:</code> and <code>volumeMounts:</code> in the deployment spec.</p>

<p>When you make changes to your application, you need to <code>docker build</code> 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.</p>

<p>(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 <code>docker run</code> 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 <code>node_modules</code> 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 <code>node_modules</code>.)</p>
