How to access Kubernetes container environment variables from Next.js application?

11/27/2019

In my next.config.js, I have a part that looks like this:

module.exports = {
  serverRuntimeConfig: { // Will only be available on the server side
    mySecret: 'secret'
  },
  publicRuntimeConfig: { // Will be available on both server and client
    PORT: process.env.PORT,
    GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
    BACKEND_URL: process.env.BACKEND_URL
  }

I have a .env file and when run locally, the Next.js application succesfully fetches the environment variables from the .env file.

I refer to the env variables like this for example:

axios.get(publicRuntimeConfig.BACKOFFICE_BACKEND_URL)

However, when I have this application deployed onto my Kubernetes cluster, the environment variables set in the deploy file are not being collected. So they return as undefined.

I read that .env files cannot be read due to the differences between frontend (browser based) and backend (Node based), but there must be some way to make this work.

Does anyone know how to use environment variables saved in your pods/containers deploy file on your frontend (browser based) application?

Thanks.

EDIT 1:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "38"
  creationTimestamp: xx
  generation: 40
  labels:
    app: appname
  name: appname
  namespace: development
  resourceVersion: xx
  selfLink: /apis/extensions/v1beta1/namespaces/development/deployments/appname
  uid: xxx
spec:
  progressDeadlineSeconds: xx
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: appname
      tier: sometier
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: appname
        tier: sometier
    spec:
      containers:
      - env:
        - name: NODE_ENV
          value: development
        - name: PORT
          value: "3000"
        - name: SOME_VAR
          value: xxx
        - name: SOME_VAR
          value: xxxx
        image: someimage
        imagePullPolicy: Always
        name: appname
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 3000
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
  conditions:
  - lastTransitionTime: xxx
    lastUpdateTime: xxxx
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  observedGeneration: 40
  readyReplicas: 1
  replicas: 1
  updatedReplicas: 1
-- BURGERFLIPPER101
environment-variables
kubernetes
next.js
reactjs

1 Answer

11/27/2019

You can create a config-map and then mount it as a file in your deployment with your custom environment variables.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "38"
  creationTimestamp: xx
  generation: 40
  labels:
    app: appname
  name: appname
  namespace: development
  resourceVersion: xx
  selfLink: /apis/extensions/v1beta1/namespaces/development/deployments/appname
  uid: xxx
spec:
  progressDeadlineSeconds: xx
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: appname
      tier: sometier
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: appname
        tier: sometier
    spec:
      containers:
        - env:
            - name: NODE_ENV
              value: development
            - name: PORT
              value: "3000"
            - name: SOME_VAR
              value: xxx
            - name: SOME_VAR
              value: xxxx
          volumeMounts:
            - name: environment-variables
              mountPath: "your/path/to/store/the/file"
              readOnly: true
          image: someimage
          imagePullPolicy: Always
          name: appname
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 3000
              scheme: HTTP
            initialDelaySeconds: 5
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
      volumes:
        - name: environment-variables
          configMap:
            name: environment-variables
            items:
              - key: .env
                path: .env
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
  conditions:
    - lastTransitionTime: xxx
      lastUpdateTime: xxxx
      message: Deployment has minimum availability.
      reason: MinimumReplicasAvailable
      status: "True"
      type: Available
  observedGeneration: 40
  readyReplicas: 1
  replicas: 1
  updatedReplicas: 1

I added the following configuration in your deployment file:

      volumeMounts:
        - name: environment-variables
          mountPath: "your/path/to/store/the/file"
          readOnly: true
  volumes:
    - name: environment-variables
      configMap:
        name: environment-variables
        items:
          - key: .env
            path: .env

You can then create a config map with key ".env" with your environment variables on kubernetes.

Configmap like this:

apiVersion: v1
kind: ConfigMap
metadata:
  name: environment-variables
  namespace: your-namespace
data:
  .env: |
    variable1: value1
    variable2: value2
-- Muhammad Abdul Raheem
Source: StackOverflow