Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Environment variable undefined in next.config.ts when running in Docker container #77539

Open
kuanjiahong opened this issue Mar 27, 2025 · 15 comments
Labels
Runtime Related to Node.js or Edge Runtime with Next.js.

Comments

@kuanjiahong
Copy link

kuanjiahong commented Mar 27, 2025

Link to the code that reproduces this issue

https://github.com/kuanjiahong/env-var-not-defined-docker

To Reproduce

  1. Start the container with docker compose up --build
  2. Go to http://localhost:3000/
  3. Click the link

Image

Current vs. Expected behavior

Current behaviour:

You are redirected to /fail-to-rewrite which means process.env.REWRITE_URL is undefined. This logic comes from the config at next.config.ts

Screenshot showing the rewrite logic in next.config.ts
Image

Current page:
Image

Expected behaviour:

You should be redirected to https://example.com/ as defined in the docker-compose.yaml file in the REWRITE_URL environment variable

Screenshot showing the location where REWRITE_URL is defined in docker-compose.yaml
Image

Expected page:

Image

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 10 Enterprise
  Available memory (MB): 32562
  Available CPU cores: 8
Binaries:
  Node: 22.12.0
  npm: 11.0.0
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 15.3.0-canary.24 // Latest available version is detected (15.3.0-canary.24).
  eslint-config-next: N/A
  react: 19.0.0
  react-dom: 19.0.0
  typescript: 5.8.2
Next.js Config:
  output: standalone

Which area(s) are affected? (Select all that apply)

Runtime

Which stage(s) are affected? (Select all that apply)

next start (local)

Additional context

I found this issue when I run my project with Docker.

Here are my Docker information:

Client:
 Version:           28.0.1
 API version:       1.48
 Go version:        go1.23.6
 Git commit:        068a01e
 Built:             Wed Feb 26 10:41:52 2025
 OS/Arch:           windows/amd64
 Context:           desktop-linux

Server: Docker Desktop 4.39.0 (184744)
 Engine:
  Version:          28.0.1
  API version:      1.48 (minimum version 1.24)
  Go version:       go1.23.6
  Git commit:       bbd0a17
  Built:            Wed Feb 26 10:41:16 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.7.25
  GitCommit:        bcc810d6b9066471b0b6fa75f557a15a1cbf31bb
 runc:
  Version:          1.2.4
  GitCommit:        v1.2.4-0-g6c52b3f
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

When inspecting the environment variables in the container. The environment variable REWRITE_URL exist

Image

These issues might be related:
#77436
#77448

@github-actions github-actions bot added the Runtime Related to Node.js or Edge Runtime with Next.js. label Mar 27, 2025
@djsisson
Copy link

@kuanjiahong can you add it as a build arg

services:
  frontend:
    build: 
      context: .
      args:
        - REWRITE_URL=https://www.example.com
    ports: "3000:3000"

@kuanjiahong
Copy link
Author

@djsisson I have tried and it still does not work. For context, I only changed the docker-compose.yaml. I did not update the Dockerfile to read the args from the docker-compose.yaml

@djsisson
Copy link

@kuanjiahong yes sorry in your dockerfile you would need to add:

ARG REWRITE_URL

in your build stage, before the build command

@kuanjiahong
Copy link
Author

kuanjiahong commented Mar 28, 2025

@djsisson Great, your solution works. However, I wonder if there is a way to do it without using ARG

For context, this is my edited Dockerfile

# syntax=docker.io/docker/dockerfile:1

FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base 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

# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
RUN \
  if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
  elif [ -f package-lock.json ]; then npm ci; \
  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
  else echo "Lockfile not found." && exit 1; \
  fi


# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ARG REWRITE_URL  <---------------------------------------------- ADDED THIS LINE

# 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 during the build.
# ENV NEXT_TELEMETRY_DISABLED=1

RUN \
  if [ -f yarn.lock ]; then yarn run build; \
  elif [ -f package-lock.json ]; then npm run build; \
  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
  else echo "Lockfile not found." && exit 1; \
  fi

# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED=1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT=3000

# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/config/next-config-js/output
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

@djsisson
Copy link

@kuanjiahong the env needs to be present during build, so either a .env file needs to be present in the build directory, or you pass it in as a build arg, and then read it using the arg command

@kuanjiahong
Copy link
Author

kuanjiahong commented Mar 28, 2025

@djsisson Understood. Based on your explanation, I decided to see what is the behaviour if I build the image first and run the docker-compose.yaml. It turns out this method also solve the issue.

Here is the workflow:

  1. Run docker build -t nextjs-docker .
  2. Change the docker-compose.yaml file as below:
services:
  frontend:
    # build: .
    image: nextjs-docker # <--- use image instead of build
    ports:
      - "3000:3000"
    environment:
      - REWRITE_URL=https://www.example.com
  1. Run docker compose up

This will solve the issue and we do not need to include ARG in the Dockerfile

(UPDATE 29/03/2025: This worfklow does not solve the issue. It worked because apparently the browser cached the route)

On the other hand, if I do it this way:

  1. Run docker build -t nextjs-docker .
  2. Run docker run -p 3000:3000 -e REWRITE_URL=https://www.example.com nextjs-docker

This does not solve the issue as the application somehow will not be able to read the environment variable

@djsisson
Copy link

@kuanjiahong it only looked like it worked probably because the route had been cached by your browser, if you did a full refresh you would find it hadn't worked, unless you have a .env file in your build directory

passing it in as an env during runtime does nothing, as it is compiled during build time.

@djsisson
Copy link

@kuanjiahong i will add, you can check here
/app/.next/routes-manifest.json
this is created during build and is where the rewrites are defined.

@Ve2s4
Copy link

Ve2s4 commented Mar 29, 2025

This issue is such a PIA. I’ve been trying to solve it for three days now :(

@djsisson
Copy link

@Ve2s4 what issue?

@kuanjiahong
Copy link
Author

kuanjiahong commented Mar 29, 2025

@kuanjiahong it only looked like it worked probably because the route had been cached by your browser, if you did a full refresh you would find it hadn't worked, unless you have a .env file in your build directory

passing it in as an env during runtime does nothing, as it is compiled during build time.

@djsisson You are right. I tried using another browser (Mozilla Firefox) and the env was not defined.

@kuanjiahong
Copy link
Author

kuanjiahong commented Mar 29, 2025

@kuanjiahong i will add, you can check here /app/.next/routes-manifest.json this is created during build and is where the rewrites are defined.

@djsisson I got to learn something new. To see this, I ran npm run build twice:

(1) with an empty .env file in the build directory and this is the result

Image

(2) .env file with REWRITE_URL=https://example.com

Image

So it seems that next.config.ts only supports environment variable being injected during build time and not during runtime. This means the environmant variable used in next.config.ts cannot be overriden during runtime. Is this conclusion true? Or is there a way to define/override environment variable in next.config.ts during runtime?

@djsisson
Copy link

@kuanjiahong the config is only ran once at compile time, if you want dynamic rewrites just use middleware

https://nextjs.org/docs/app/api-reference/functions/next-response#rewrite

@Ve2s4
Copy link

Ve2s4 commented Mar 30, 2025

@Ve2s4 what issue?

Missing env variables in Docker. I had to pass them as ARGs and then set them in the image's env vars, which poses a security issue, I know. It’s a workaround I found somewhere, but seriously, why does Next.js handle env vars like it’s trying to win an award for absurdity.

@djsisson
Copy link

@Ve2s4 you don't need to set build vars as env vars, also you can pass in as docker secrets if you don't want to see them.
this doesn't really have anything to do with nextjs, if any build requires some kind of env var ofc it needs to be there when you build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Runtime Related to Node.js or Edge Runtime with Next.js.
Projects
None yet
Development

No branches or pull requests

3 participants