<p>I'm trying to generate some env variables when I'm deploying my code with Kubernets. What I'm trying to do is to generate a ConfigMap to get my variables, but it's not working.
I'm using azure pipelines to do my build and publish steps.</p>
<p>Dockerfile:</p>
<pre><code>FROM node:14-alpine

WORKDIR /usr/src/app

COPY package.json .

COPY . .

RUN npm cache clean --force
RUN npm install
RUN npm run build

EXPOSE 80

CMD [&quot;npm&quot;, &quot;start&quot;]
</code></pre>
<p>My azure-pipelines.yml:</p>
<pre><code>stages:
#Build Dev
- stage: BuildDev
  displayName: Build and Push Dev
  jobs:
  - job: Development
    displayName: Build and Push Dev
    timeoutInMinutes: 0
    pool:
      vmImage: ubuntu-18.04
    steps:
    - checkout: self
    - task: Docker@1
      displayName: Build Image
      inputs:
        azureSubscriptionEndpoint: my-subscription
        azureContainerRegistry: my-container-registry
        command: build
        imageName: tenant/front/dev:$(Build.BuildId)
        includeLatestTag: true
        buildContext: '**'
    - task: Docker@1
      displayName: Push Image
      inputs:
        azureSubscriptionEndpoint: my-subscription
        azureContainerRegistry: my-container-registry
        command: push
        imageName: tenant/front/dev:$(Build.BuildId)
        buildContext: '**'


#Deploy Dev
- stage: DeployDev
  displayName: Deploy Dev
  jobs:
    - deployment: Deploy
      displayName: Deploy Dev
      timeoutInMinutes: 0
      pool:
        vmImage: ubuntu-18.04
      environment: Development-Front
      strategy:
        runOnce:
          deploy:
            steps:
            - task: Kubernetes@1
              displayName: 'kubectl apply'
              inputs:
                kubernetesServiceEndpoint: 'AKS (standard subscription)'
                command: apply
                useConfigurationFile: true
                configurationType: inline
                inline: |
                  apiVersion: apps/v1beta1
                  kind: Deployment
                  metadata:
                      name: $(appNameDev)
                      labels:
                          app: $(appNameDev)
                  spec:
                      replicas: 1
                      selector:
                          matchLabels:
                              app: $(appNameDev)
                      template:
                          metadata:
                              labels:
                                  app: $(appNameDev)
                          spec:
                              containers:
                                  - name: $(appNameDev)
                                    image: tenant/front/dev:$(Build.BuildId)
                                    imagePullPolicy:
                                    env:
                                      - name: NEXT_PUBLIC_APP_API
                                        value: development
                                    ports:
                                      - name: http
                                        containerPort: 80
                                        protocol: TCP
                                    volumeMounts:
                                      - name: environment-variables
                                        mountPath: /usr/src/app/.env
                                        readOnly: true
                              volumes:
                                - name: environment-variables
                                  configMap:
                                    name: environment-variables
                                    items:
                                    - key: .env
                                      path: .env
              ---
              apiVersion: v1
              kind: Service
              metadata:
                  name: $(appNameDev)
                  labels:
                      app: $(appNameDev)
              spec:
                  type: LoadBalancer
                  ports:
                      - port: 80
                        targetPort: 80
                        protocol: TCP
                        name: http
                  selector:
                      app: $(appNameDev)
              ---
              apiVersion: v1
              kind: ConfigMap
              metadata:
                name: environment-variables
              data:
                .env: |
                  NEXT_PUBLIC_APP_API=development
                  API=http://another.endpoint.com/serverSide
</code></pre>
<p>When I'm trying to access this NEXT_PUBLIC_APP_API variable, I'm receiving undefined. In my next.config.js, I'm exporting the variable as publicRuntimeConfig.</p>

<p>If you are using GitHub actions, the first thing is to add a step in your image build process to include dynamic variables</p>
<pre><code>  - name: Create variables
    id: vars
    run: |
      branch=${GITHUB_REF##*/}
      echo &quot;API_URL=API_${branch^^}&quot; &gt;&gt; $GITHUB_ENV
      echo &quot;APP_ENV=APP_${branch^^}&quot; &gt;&gt; $GITHUB_ENV
      echo &quot;BASE_URL=BASE_${branch^^}&quot; &gt;&gt; $GITHUB_ENV
      sed -i &quot;s/GIT_VERSION/${{ github.sha }}/g&quot; k8s/${branch}/api-deployment.yaml
</code></pre>
<p>The second step is to build the docker image with extra arguments, if you are using another CI, just add the variables directly in the build args as below:</p>
<pre><code>--build-arg PROD_ENV=NEXT_PUBLIC_API_URL=${{ secrets[env.API_URL] }}\nNEXT_PUBLIC_BASE_URL=${{ secrets[env.BASE_URL]}}\nNEXT_PUBLIC_APP_ENV=${{ secrets[env.APP_ENV] }}
</code></pre>
<p>Pay attention to the <code>\n</code> to skip lines and docker to be able to understand that you are sending multiple variables to the build process.</p>
<p>The last thing is to add the extra args inside the Dockerfile</p>
<pre><code># Install dependencies only when needed
FROM node:16.13.0-alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install

# Rebuild the source code only when needed
FROM node:16.13.0-alpine AS builder
ARG PROD_ENV=&quot;&quot;
WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN printf &quot;$PROD_ENV&quot; &gt;&gt; .env.production
RUN yarn build

# Production image, copy all the files and run next
FROM node:16.13.0-alpine AS runner
WORKDIR /app

ENV NODE_ENV production

# You only need to copy next.config.js if you are NOT using the default configuration
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/.env* ./
COPY --from=builder /app/next-i18next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
RUN chown -R nextjs:nodejs /app/.next
USER nextjs

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry.
RUN npx next telemetry disable

CMD [&quot;yarn&quot;, &quot;start&quot;]
</code></pre>
<p>I send as extra args PROD_ENV and then build a .env.production file on the fly with the required values.</p>
<p>Mark as answer if it helps you</p>
