Kubernetes share volume between containers inside a Deployment

9/24/2017

Before posting this question I followed this answer How to mimic '--volumes-from' in Kubernetes but it didn't work for me.

I have 2 containers:

  • node: its image contains all the files related to the app ( inside /var/www )
  • nginx: it needs to access the files inside the node image (especially the /clientBuild folder where I have all the assets)

What is inside the node image:

$ docker run node ls -l
> clientBuild/
> package.json
> ...

A part of the nginx.prod.conf:

location ~* \.(jpeg|jpg|gif|png|ico|css|js|gz|map|json)$ {
  include /etc/nginx/mime.types;
  root /usr/local/nginx/html/clientBuild/;
}

And the the deployment setup:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: pwa-app-production
  labels:
    app: MyApp
spec:
  replicas: 1
  template:
    metadata:
      name: app
      labels:
        app: MyApp
        env: production
    spec:
      containers:
      - name: nginx
        image: nginx
        command: [nginx, -c, /nginx.prod.conf, -g, 'daemon off;']
        resources:
          limits:
            memory: "500Mi"
            cpu: "100m"
        imagePullPolicy: Always
        volumeMounts:
          - mountPath: /usr/local/nginx/html
            name: pwa-disk
            readOnly: true
        ports:
        - name: nginx
          containerPort: 80
      initContainers:
      - name: node
        image: node
        command: [npm, start]
        resources:
          limits:
            memory: "500Mi"
            cpu: "100m"
        imagePullPolicy: Always
        volumeMounts:
          - mountPath: /var/www
            name: pwa-disk
        ports:
        - name: app
          containerPort: 3000
        - name: api
          containerPort: 3001
      volumes:
        - name: pwa-disk
          emptyDir: {}

I first attempt to put both images in the same containers key, but i got: /var/www/package.json not found on npm start

Then I moved it inside the initContainers but now I only have a notice that it failed, but it does not tell me why. View logs does not show any details too.

Notice that when I remove volume part, the npm start works.

enter image description here

-- Ha Ja
kubectl
kubernetes

1 Answer

9/25/2017

I assume your assets are already packaged inside the image at /var/www. If you mount an emptyDir volume at that path, then everything there gets overriden with the content of the emptyDir volume - which initially is nothing. That means all your assets are deleted through that mount - which is why your node server is most likely failing.

What you want to do is mount the emptyDir volume at some other path, say /data. Then you override your node containers cmd with cp -r /var/www/* /data to copy the assets into yourpwa-disk volume. Now, you can mount this volume into your nginx container.

I think there is a misunderstanding on how initContainers work. They are meant to terminate. They run BEFORE any other container is started - no other container inside your pod is started until your initContainers have successfully terminated. So most likely you do not want to start your node server as an initContainer. I guess your node server is not supposed to terminate, in which case your nginx container will never start up. Instead, you might want to declare your node server together with your nginx inside the containers section. Additionally, you also add your node container with an overridden cmd (cp -r /var/www/* /data) to the initContainers section, to copy the assets to a volume. The whole thing might look sth like that:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: pwa-app-production
  labels:
    app: MyApp
spec:
  replicas: 1
  template:
    metadata:
      name: app
      labels:
        app: MyApp
        env: production
    spec:
      containers:
      - name: nginx
        image: nginx
        command: [nginx, -c, /nginx.prod.conf, -g, 'daemon off;']
        resources:
          limits:
            memory: "500Mi"
            cpu: "100m"
        imagePullPolicy: Always
        volumeMounts:
          - mountPath: /usr/local/nginx/html
            name: pwa-disk
            readOnly: true
        ports:
        - name: nginx
          containerPort: 80
      - name: node
        image: node
        command: [npm, start]
        resources:
          limits:
            memory: "500Mi"
            cpu: "100m"
        imagePullPolicy: Always
        ports:
        - name: app
          containerPort: 3000
        - name: api
          containerPort: 3001

      initContainers:
      - name: assets
        image: node
        command: [bash, -c]
        args: ["cp -r /var/www/* /data"]
        imagePullPolicy: Always
        volumeMounts:
          - mountPath: /data
            name: pwa-disk
      volumes:
        - name: pwa-disk
          emptyDir: {}
-- fishi0x01
Source: StackOverflow