<p>I have a next js app that I am trying to deploy to a kubernetes cluster as a deployment. Parts of the application contain axios http requests that reference an environment variable containing the value of a backend service.</p>
<p>If I am running locally, everything works fine, here is what I have in my <code>.env.local</code> file:</p>
<pre><code>NEXT_PUBLIC_BACKEND_URL=http://localhost:8080
</code></pre>
<p>Anywhere in the app, I can successfully access this variable with <code>process.env.NEXT_PUBLIC_BACKEND_URL</code>.</p>
<p>When I create a kubernetes deployment, I try to inject that same env variable via a configMap and the variable shows as <code>undefined</code>.</p>
<p><code>deployment.yaml</code></p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: my-site-frontend
  name: my-site-frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-site-frontend
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: my-site-frontend
    spec:
      containers:
      - image: my-site:0.1
        name: my-site
        resources: {}
        envFrom:
        - configMapRef:
            name: my-site-frontend
      imagePullSecrets:
      - name: dockerhub
</code></pre>
<p><code>configMap.yaml</code></p>
<pre><code>apiVersion: v1
kind: ConfigMap
metadata:
  name: my-site-frontend
data:
  NEXT_PUBLIC_BACKEND_URL: backend_service
</code></pre>
<p>When I run the deployment and expose the application via a nodePort, I see these environment variables as <code>undefined</code> in my browser console. All api calls to my backend_service (ClusterIP) fail as you can imagine.</p>
<p>I can see the env variable is present when I exec into the running pod.</p>
<pre><code>my-mac:manifests andy$ k get pods

NAME                                READY   STATUS    RESTARTS   AGE
my-site-frontend-77fb459dbf-d996n   1/1     Running   0          25m

---

my-mac:manifests andy$ k exec -it my-site-frontend-77fb459dbf-d996n -- sh

---

/app $ env | grep NEXT_PUBLIC

NEXT_PUBLIC_BACKEND_URL=backend_service
</code></pre>
<p>Any idea as to why the build process for my app does not account for this variable?</p>
<p>Thanks!</p>

Andy
<p><strong>Make sure kubernetes part did the job right</strong></p>
<p>First what's needed to check if environment actually get to the pod. Your option works, however there are cases when <code>kubectl exec -it pod_name -- sh / bash</code> creates a different session and all configmaps can be reloaded again.</p>
<p>So let's check if it works right after pod is created and environment is presented.</p>
<p>I created a deployment with your base, put <code>nginx</code> image and extended <code>spec</code> part with:</p>
<pre><code>command: [&quot;/bin/bash&quot;, &quot;-c&quot;]
args: [&quot;env | grep BACKEND_URL ; nginx -g \&quot;daemon off;\&quot;&quot;]
</code></pre>
<p>Right after pod started, got logs and confirmed environment is presented:</p>
<pre><code>kubectl logs my-site-frontend-yyyyyyyy-xxxxx -n name_space | grep BACKEND
NEXT_PUBLIC_BACKEND_URL=SERVICE_URL:8000
</code></pre>
<p><strong>Why browser doesn't show environment variables</strong></p>
<p>This is part is more tricky. Based on some research on <code>next.js</code>, variables should be set before project building (more details <a href="https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser" rel="nofollow noreferrer">here</a>):</p>
<blockquote>
<p>The value will be inlined into JavaScript sent to the browser because
of the NEXT_PUBLIC_ prefix. This inlining occurs at build time, so
your various NEXT_PUBLIC_ envs need to be set when the project is
built.</p>
</blockquote>
<p>You can also see a <a href="https://github.com/vercel/next.js/tree/canary/examples/environment-variables" rel="nofollow noreferrer">good example of using environment variables</a> from <code>next.js</code> github project. You can try <code>Open in StackBlitz</code> option, very convenient and transparent.</p>
<p>At this point you may want to introduce DNS names since IPs can be changed and also different URL paths for front and back ends (depending on the application, below is an example of <code>react</code> app)</p>
<p><strong>Kubernetes ingress</strong></p>
<p>If you decide to use DNS, then you may run into necessity to route the traffic.</p>
<p>Short note what ingress is:</p>
<blockquote>
<p>An API object that manages external access to the services in a
cluster, typically HTTP.</p>
<p>Ingress may provide load balancing, SSL termination and name-based
virtual hosting.</p>
</blockquote>
<p>Why this is needed. Once you have DNS endpoint, frontend and backend should be separated and have the same domain name to avoid any CORS policies and etc (this is possible to resolve of course, here's more for testing and developing on a local cluster).</p>
<p><a href="https://stackoverflow.com/questions/67470540/react-is-not-hitting-django-apis-on-kubernetes-cluster/67534740#67534740">This is a good case</a> for solving issues with <code>react</code> application with <code>python</code> backend. Since <code>next.js</code> is a an open-source React front-end development web framework, it should be useful.</p>
<p>In this case, there's a frontend which is located on <code>/</code> and has service on <code>3000</code> port and backend which located on <code>/backend</code> (please see deployment with example).
Then below is how to setup <code>/etc/hosts</code>, test it and have the deployed app work.</p>
<p>Useful links:</p>
<ul>
<li><a href="https://kubernetes.io/docs/concepts/services-networking/ingress/" rel="nofollow noreferrer">kubernetes ingress and how to start with</a></li>
<li><a href="https://github.com/fivecatscats/ToDoList" rel="nofollow noreferrer">repository with all necessary yamls</a> where the SO answer is linked to</li>
</ul>
