Next.js Discord

Discord Forum

NEXT_PUBLIC env variables unavailable client side when using docker.

Answered
American black bear posted this in #help-forum
Open in Discord
Avatar
American black bearOP
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:
  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 American black 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! ❤
View full answer

35 Replies

Avatar
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
Avatar
American black bearOP
so just adding this script to my root-layout will fix the problem?
Avatar
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.
Avatar
American black bearOP
thanks will try
Avatar
American black 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 env
Avatar
after Dockerfile has finished building and you run the container, are th serverside envs available?
the*
and if so, only the PUBLIC envs that u define in the same .env are not available?
Avatar
American black bearOP
all env variables are available server side but I cannot access any client side
Avatar
so the public ones are also available?
on the server
Avatar
American black bearOP
yes
Avatar
u are only using this @t3-oss because of checking the type of your own envs?
Avatar
American black bearOP
yeah to throw an error if the user has configured them wrongly
Avatar
ah i see
so its like a premade app that a user can deploy
like that
hmmm
Avatar
American black bearOP
yeah
like an e-commerce shop
Avatar
what happens if u explicity define the public envs in the next config
Avatar
American black bearOP
havent tried that
that will probably work tho
Avatar
do that and see if those will be available in the client bundle
cause thats what its for
Avatar
American black 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
Avatar
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
Avatar
American black bearOP
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! ❤
Answer
Avatar
American black bear
Hi @American black bear ,
I am running into same issue and could you please share your solution (git repo), just in case?
Avatar
American black bearOP
Here is the [repo](https://github.com/AleksaSimovic1/store-docker).

The files of interest are:

- .env.example
- prepare.sh
- migrate.sh


Basically 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.