NEXT_PUBLIC env variables unavailable client side when using docker.
Answered
Sun bear posted this in #help-forum
Sun bearOP
I am serving my next.js frontend using Docker. In my
The environment variables work as expected on server, meaning that Next.js does "receive" the env file specified in
Here are some code examples:
It is worth noting that if I try to display
compose.yml file I inject my root .env file using env_file property of my frontend service.The environment variables work as expected on server, meaning that Next.js does "receive" the env file specified in
env_file, but when I try to access variables in my client components they are "undefined".Here are some code examples:
frontend:
build:
context: ./frontend
dockerfile: ./docker/Dockerfile
container_name: store-frontend
ports:
- 8000
depends_on:
- backend
networks:
- internal
restart: unless-stopped
# Specifies the env file
env_file:
- .env"use client"
import env from "~/env"
export default function ClientComponent() {
return <h1>{env.NEXT_PUBLIC_COMPANY_NAME}</h1>
}
// html on browser
// <h1></h1>It is worth noting that if I try to display
NEXT_PUBLIC_COMPANY_NAME in my server components it works as expected.Answered by Sun bear
I've created a
Thank you guys for help! ❤
./migrate.sh script that user runs before starting docker compose. The script copies my root .env file into subdirectories that are using environment at build time, fixing my issue where NEXT_PUBLIC_ environment variables were unavailable in my client components. This only adds 1 extra step when deploying the app and removes the issue with editing multiple environment files, but still requires the user to re-run it every time he makes changes to the .env.Thank you guys for help! ❤
35 Replies
@Sun bear I am serving my next.js frontend using Docker. In my `compose.yml` file I inject my root `.env` file using `env_file` property of my frontend service.
The environment variables work as expected on server, meaning that Next.js does "receive" the env file specified in `env_file`, but when I try to access variables in my client components they are "undefined".
Here are some code examples:
yml
frontend:
build:
context: ./frontend
dockerfile: ./docker/Dockerfile
container_name: store-frontend
ports:
- 8000
depends_on:
- backend
networks:
- internal
restart: unless-stopped
# Specifies the env file
env_file:
- .env
ts
"use client"
import env from "~/env"
export default function ClientComponent() {
return <h1>{env.NEXT_PUBLIC_COMPANY_NAME}</h1>
}
// html on browser
// <h1></h1>
It is worth noting that if I try to display `NEXT_PUBLIC_COMPANY_NAME` in my server components it works as expected.
the env var needs to be present when you build the app, which is likely not what happened in your case.
you may want to use this package: https://github.com/expatfile/next-runtime-env
you may want to use this package: https://github.com/expatfile/next-runtime-env
Sun bearOP
so just adding this script to my root-layout will fix the problem?
i don't know, i never used it myself. but if you can't get the env var before build, that's the only way to get it to work as far as i can tell.
Sun bearOP
thanks will try
Sun bearOP
this did not work, might be worth mentioning that I am using typesafe env from
@t3-oss if that changes anything how the next.js processes envthe*
and if so, only the PUBLIC envs that u define in the same .env are not available?
Sun bearOP
all env variables are available server side but I cannot access any client side
so the public ones are also available?
on the server
Sun bearOP
yes
u are only using this @t3-oss because of checking the type of your own envs?
Sun bearOP
yeah to throw an error if the user has configured them wrongly
Sun bearOP
yeah
like an e-commerce shop
what happens if u explicity define the public envs in the next config
Sun bearOP
havent tried that
that will probably work tho
do that and see if those will be available in the client bundle
cause thats what its for
Sun bearOP
yeah but I kinda want to avoid that since I have a bash script that user runs to deploy the app and it is much easier if I only have a single .env file
another approach that worked before was copying the .env from root to each of the apps using it
the script asks user for a few thing and auto generates the keys and other domain stuff
if those public envs never change the name why would be that a problem
i guess the user has some type of control over a webinterface so he isnt touching the source
i guess it only makes next aware of that the envs exist but it doesnt need to be predefined when building
just the name should not change
Sun bearOP
I've created a
Thank you guys for help! ❤
./migrate.sh script that user runs before starting docker compose. The script copies my root .env file into subdirectories that are using environment at build time, fixing my issue where NEXT_PUBLIC_ environment variables were unavailable in my client components. This only adds 1 extra step when deploying the app and removes the issue with editing multiple environment files, but still requires the user to re-run it every time he makes changes to the .env.Thank you guys for help! ❤
Answer
@Sun bear I've created a `./migrate.sh` script that user runs before starting `docker compose`. The script copies my root `.env` file into subdirectories that are using environment at build time, fixing my issue where `NEXT_PUBLIC_` environment variables were unavailable in my client components. This only adds 1 extra step when deploying the app and removes the issue with editing multiple environment files, but still requires the user to re-run it every time he makes changes to the `.env`.
Thank you guys for help! ❤
American black bear
Hi @Sun bear ,
I am running into same issue and could you please share your solution (git repo), just in case?
I am running into same issue and could you please share your solution (git repo), just in case?
@American black bear Hi <@696792098996879379> ,
I am running into same issue and could you please share your solution (git repo), just in case?
Sun bearOP
Here is the [repo](https://github.com/AleksaSimovic1/store-docker).
The files of interest are:
Basically you create a
The files of interest are:
- .env.example
- prepare.sh
- migrate.shBasically you create a
.env.example file in which you create a template for your env variables. Then you create a root .env file using prepare.sh. This script auto generates secrets, domain stuff based on .env.example. You edit the rest manually and before starting the container run migrate.sh script to copy the root .env to all the apps that depend on it.