Replies: 46 comments 72 replies
-
any update ? |
Beta Was this translation helpful? Give feedback.
-
Guys its bothering me also, the same problem. Fighting with it for like a weak now, tried a lot of stuff. Any news how nextjs can swallow .env file and make client side env variables work? |
Beta Was this translation helpful? Give feedback.
-
You cannot switch I guess you could expose those variables in Also, your variables won't be embedded anymore, and may or may not be correctly crawled if you have a fallback page ( |
Beta Was this translation helpful? Give feedback.
-
Why can’t you execute a bash script to generate at run time?
…On Sat, Oct 24, 2020 at 5:17 AM Alexei Gaidulean ***@***.***> wrote:
@balazsorban44 <https://github.com/balazsorban44> Man thanks. I've read
your comment carefully, re-read docs and actually made it working.
// pages/_app.tsxTestAutoApp.getInitialProps = async (appContext: AppContext) => {
const appProps = await App.getInitialProps(appContext)
const {
publicRuntimeConfig: { PROJECT_API },
} = getConfig()
console.log('PROJECT_API', PROJECT_API) // Here project API is available
return { ...appProps }}
The idea is to opt-out of this
https://nextjs.org/docs/advanced-features/automatic-static-optimization
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#17641 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AHNS74M5QRLWOM2EAGEWWYTSMKSSDANCNFSM4SFJ2QOQ>
.
|
Beta Was this translation helpful? Give feedback.
-
@firefart did you find out any workaround for this issue? I am also into the same phase now. |
Beta Was this translation helpful? Give feedback.
-
Hi! @firefart Maybe you can use this approach, first set enviroment variable with a specific string in build time and then use an entrypoint file to replace this string with the docker enviroment variabless value. I don't know if you lose some benfits of next.js Docker file:
entrypoint.sh
Docker run:
|
Beta Was this translation helpful? Give feedback.
-
might be an old question but I solved this issue using Docker build arguments (ARG)
When building my image
When checking the image the .env.production content:
This way doesn't affect static optimization and doesn't require custom config file. |
Beta Was this translation helpful? Give feedback.
-
Have you tried using Docker BuildKit Secrets? They pretty much solve this use case, if your build system/CI can support BuildKit which is a relatively new Docker feature. Using a command like... RUN --mount=type=secret,id=env,dst=/path/to/your/next/app/.env.production.local ...you can mount the env file in your Next application temporarily during the build process, then remove it later. This causes Next to compile in the |
Beta Was this translation helpful? Give feedback.
-
My approach is to dynimc create a |
Beta Was this translation helpful? Give feedback.
-
Here's the way i'm doing it at the moment that I'm comfortable with: @andrewmclagan pointed out that his package solves this problem in a similar manner but it seems to be directly embedding the https://github.com/andrewmclagan/react-env/ Setupyarn add @beam-australia/react-env entrypoint.sh #!/bin/sh
set -e
# Generate env for runtime use
yarn react-env --env APP_ENV
# Execute any subsequent command
exec "$@"
Dockerfile FROM node:alpine
WORKDIR /app
(...) truncated, all the other build tasks
# You can choose to put the entrypoint with yarn react-env here
# but I've chosen to use an entrypoint script instead
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
CMD ["yarn", "start"] __document.js <Head>
<script type="text/javascript" src="/__ENV.js" />
</Head> .env.staging REACT_APP_SECRET=sekret page.js import env from '@beam-australia/react-env';
<p>{env('SECRET')}</p> Builddocker build -t next-app -f Dockerfile . UsageAt this point we have an image with no environment values in the built image. Assuming we're deploying for the staging environment, running the following will allow us to:
docker run -p 8080:3000 --env APP_ENV=staging -v $(pwd)/.env.staging:/app/.env.staging next-app After running the command, the
|
Beta Was this translation helpful? Give feedback.
-
Here's another workaround to insert environment variables for runtime client-side rendering: https://github.com/sparanoid/env.sh This is simply a bash version of react-env, which does not require you to build your project inside the container. The benefit of this method can help you avoid multistage Dockerfile. You can build your Next.js project in GitHub Actions. And only # A simplified version of https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
FROM node:16-alpine AS runner
# Install bash for env.sh
RUN apk add --no-cache bash
WORKDIR /app
# You only need to copy next.config.js if you are NOT using the default configuration
COPY next.config.js ./
COPY public ./public
COPY package.json .env env.sh ./
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY .next/standalone ./
COPY .next/static ./.next/static
EXPOSE 3000
ENV PORT 3000
RUN chmod +x ./env.sh
ENTRYPOINT ["./env.sh"]
CMD ["node", "server.js"] |
Beta Was this translation helpful? Give feedback.
-
I'm replacing environment variables during runtime using the entrypoint technique that replaces the values (#17641 (comment)). It mostly works but I have a weird behavior. Here is what I check in a component:
It logs So I checked the built file (after the value injection) to retrieve this log: Why doesn't it print out I'm suspecting static generation, but I'm not sure to understand. Can someone explain to me? |
Beta Was this translation helpful? Give feedback.
-
This solution worked for me: https://raphaelpralat.medium.com/system-environment-variables-in-next-js-with-docker-1f0754e04cde |
Beta Was this translation helpful? Give feedback.
-
The solid examples above are useful for getting the env variables from .env files or in the docker container.. but having trouble tackling a case where the docker container is built and deployed to ec2/fargate, and the env variables are passed into the |
Beta Was this translation helpful? Give feedback.
-
I faced the same issue with the app router variant and came up with the following solution Create a server action that returns the value of the NEXT_PUBLIC variable: "use server"
export const NEXT_PUBLIC_FOO = () => {
return process.env.NEXT_PUBLIC_FOO || missing
}
// even more vars if needed In the client component i call the function and store the value in a state that i use in the rest of the component. "use client"
import { NEXT_PUBLIC_FOO } from '@/lib/publicVars'
import { useEffect, useState } from 'react'
export default function PageFoo() {
const [foo,setFoo] = useState<string>('')
useEffect(()=>{
const init = async()=>{
setFoo(await NEXT_PUBLIC_FOO())
}
init()
})
return (
<div>{foo}</div>
)
} this way the string is not hardcoded and will be requested from the server each time the component gets loaded. |
Beta Was this translation helpful? Give feedback.
-
After many hours of searching for answers, it turns out that I had placed the
and docker build -t tagname --build-arg NEXT_PUBLIC_BACKEND_URL=http://localhost:8000 . |
Beta Was this translation helpful? Give feedback.
-
Just published a detailed guide about using public env variables along with Docker. You can find the guide on my blog https://www.vorillaz.com/nextjs-docker-env, and you can also explore the sample application as well https://github.com/vorillaz/tutorials/tree/main/docker-nextjs-env |
Beta Was this translation helpful? Give feedback.
-
We're loading many of env variables as constants like this: |
Beta Was this translation helpful? Give feedback.
-
Here is what I did to solve the issue, I took inspiration from @rboixaderg with the I have put this all into a gist for anyone interested https://gist.github.com/kevcoxe/4e8030fb5c2c1a580137d5e2e202812b |
Beta Was this translation helpful? Give feedback.
-
This So here's the bare-bones server, without the need for any new dependencies: import http from 'http';
const server = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => {
try {
switch (req.url) {
case '/env': {
const envData: { [envKey: string]: string | undefined } = {};
for (const k of Object.keys(process.env)) {
if (k.startsWith('NEXT_PUBLIC_') || k.startsWith('DYNAMIC_NEXT_PUBLIC_'))
envData[k] = process.env[k];
}
res.end(JSON.stringify(envData));
return;
}
case '/shutdown':
res.end();
return process.exit(0);
default:
res.writeHead(404);
res.end();
}
} catch (err) {
console.error(err);
if (typeof err === 'object' && err != null && 'message' in err && typeof err.message === 'string') {
res.write(err.message);
}
res.writeHead(500);
res.end();
}
});
server.listen(3001, () => console.log('Serving descriptions on port', 3001)); This is how I fetch it at the let fetchedData: { rawEnvData: string; } | undefined = undefined;
export default async function RootLayout({ children }: { children: React.ReactNode }) {
if (fetchedData == null) {
const envRes = await fetch('http://localhost:3001/env', { cache: 'no-store' });
if (!envRes.ok) {
throw new Error(`Fetching the env data failed: ${envRes.status} (${envRes.statusText})`);
}
fetchedData = { rawEnvData: await envRes.text() };
if (process.env.NODE_ENV === 'production') // on dev, runtime recompiles will fail otherwise
void (await fetch('http://localhost:3001/shutdown', { cache: 'no-store' }));
}
return (
<html>
<body>
<MyNonRSCComponent envData={fetchedData.rawEnvData}>
{children}
</MyNonRSCComponent>
</body>
</html>
);
} Of course, this In the "scripts": {
"dev": "npm run dev:serve-nextjs-data & next",
"build": "next build && npm run build:serve-nextjs-data",
"start": "npm run start:serve-nextjs-data & next start",
"dev:serve-nextjs-data": "node -r ts-node/register --env-file=.env $([ -f .env.local ] && echo \"--env-file .env.local \") serveNextjsData/serve.ts",
"build:serve-nextjs-data": "cd serveNextjsData && tsc && cd ..",
"start:serve-nextjs-data": "node --env-file=.env serveNextjsData/serve.js",
} In case you have a multi-staged I'm still startled that Next.js enforces such an error-prone, pointlessly complex way to comply with a common paradigm for managing deployments. If somebody has some proposols on how to improve that approach, I'ld be grateful, too. I'm especially unhappy how I start both processes at once, |
Beta Was this translation helpful? Give feedback.
-
Just in case anyone else runs into this on Next 14 with App Router... I opted for build once, deploy everywhere and created a simple NextJS API route that accessed the env vars and gave them back to the UI to persist to a store or to use directly in CSR comps, etc. The key is using Here's a full example:
And I tested it out with a quick deployment to AWS ECS like this:
Side note, my API is running in ECS as well so I made my NextJS API dir like this |
Beta Was this translation helpful? Give feedback.
-
I just deployed my next js application on my K8s server. After setting up ingress, it works fine. And now, I would like to use ConfigMap to mount the .env to redefine the env that I define when the image was being built. |
Beta Was this translation helpful? Give feedback.
-
@vorillaz's solution seems to be working relatively well. The idea is to have the environment variables exported from server side to client side components. I made a little bit tweak on his above solution to ensure that the environment variables are initialized only once.
To use the provider:
You might want to do something like this in layout.tsx:
On Docker / K8S side, set |
Beta Was this translation helpful? Give feedback.
-
The solution from the following link: https://dev.to/vorillaz/nextjs-with-public-environment-variables-in-docker-4ogf worked very well for me, especially the one from the subtitle: "A More Consistent Approach." |
Beta Was this translation helpful? Give feedback.
-
And how do you handle statics contents generated at build time ? 1/ Statics contents will be generated, for example, in a github/gitlab pipeline with test env |
Beta Was this translation helpful? Give feedback.
-
So i am writing (on monday) after three days[Friday, Saturday & Sunday] of unsuccessful attempts.
on top of the server side file where you are referencing the variables dynamically. This is the code which I made working with above.
and this is the client side code which I am using to call the above and it works now in production.
|
Beta Was this translation helpful? Give feedback.
-
For those still interest, you can also use global exposed variables both to client and server components with proper validation as well. |
Beta Was this translation helpful? Give feedback.
-
I've been following this topic for a while and I found a solution that worked for my case: This is what I have. My import { env, PublicEnvScript } from "next-runtime-env"
export default function RootLayout(){
const publicEnv = env("NEXT_PUBLIC_ENV_TEST")
return (
<html>
<head>
<PublicEnvScript />
</head>
<body>
<p>public env test: {publicEnv}</p>
</body>
</html>
)
} My # Use Docker's Node Alpine Linux image as the base Image
FROM node:alpine3.20 AS base
# Set the working directory inside the container
WORKDIR /app
# Copy `package.json` & `package-lock`.json to the root folder
COPY package*.json ./
# Install the node module dependencies
RUN npm install
# Copy everything else
COPY . .
# Build the Next.js app
RUN npm run build
# Set the environment
ENV NODE_ENV=production
# Expose the port Next.js needs
EXPOSE 3000
# Run the server!
CMD ["node", ".next/standalone/server.js"] My services:
nextjs:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- NEXT_PUBLIC_ENV_TEST="hello world" Now you only need to build the container the first time! If you change the |
Beta Was this translation helpful? Give feedback.
-
Hi @leerob, I’d really appreciate some guidance on what feels like a recurring pain point: handling environment variables for a Dockerized Next.js app with a single image and multiple environments—specifically without relying on platforms like Vercel. The Next.js docs touch on the basics, but they don’t provide enough detail for this use case. For example:
If the image is built once and then deployed to multiple environments (e.g., staging, production), what’s the recommended approach for injecting the correct variables at runtime? Most solutions I’ve found feel hacky or overly complex like using a script that replaces the variables, using a npm library just to use runtime environments or having to call any of the Dynamic APIs to opt in into runtime environments (exclusively for server side components). Would love to hear your thoughts on this (or see it covered in the docs more in depth). I know I’m not alone in struggling with this. Thanks! |
Beta Was this translation helpful? Give feedback.
-
Hi,
I'm currently trying to dockerize a next.js app which will be built using github actions, the image is pushed to githubs container registry and after that it is deployed to our kubernetes cluster. We use the same image for multiple stages in our environment (dev, staging, prod) and all configuration values are passed to the docker image via secrets or env variables upon start.
Now a problem arises when using browser exposed env variables in next.js with
NEXT_PUBLIC_....
(in our case needed for google recaptcha and stripe.js):It seems like all
NEXT_PUBLIC_
env vars need to be defined at build time, as thenext build
command replaces them with the actual values in the generated JS code. But as the env keys differ for each environment (test has other public keys as prod), we can't provide them at build time to the image without having to build separate images for each env which we would like to prevent.Is there a clean way of providing these env vars at runtime instead? The docs at https://nextjs.org/docs/basic-features/environment-variables are not really helpful in this case.
Putting the
next build
step in the entrypoint of the dockerfile so it will be executed upon start is also no option, as the build steps take a huge amount of memory.Thanks!
Dockerfile example:
Beta Was this translation helpful? Give feedback.
All reactions