System environment variables at build time? What to do when building with docker? #14030
-
|
I figured that the environment variables are needed at build time, for When building with docker-compose from a dockerfile, we can set up the environment variables for the system, using the We cannot necessarily read from a What is the usual best practice in this case? Read from the system variables without an This is my setup: docker-compose.yml version: '3.7'
services:
fe:
build: ./
ports:
- '3000:80'
environment:
NEXT_PUBLIC_API_URI: arbitrary_valueDockerfile FROM node:12.18.0-alpine
WORKDIR /app/
COPY . .
RUN npm i
RUN npm run build
EXPOSE 3000
EXPOSE 80
CMD ["npm", "run", "serve"]In this case here. "arbitrary_value" is not available in the browser, reading with |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
|
Also, one more thing. In that case is the only option using |
Beta Was this translation helpful? Give feedback.
-
|
For build time values you need to use build args instead of environment variables. Here are the updated files: # docker-compose.yml
version: '3.7'
services:
fe:
build: ./
ports:
- '3000:80'
# the build args are defined by this key
args:
NEXT_PUBLIC_API_URI: arbitrary_value# Dockerfile
FROM node:12.18.0-alpine
WORKDIR /app/
# here we are reading the value from the build args and inserting into the environment variables
ARG NEXT_PUBLIC_API_URI
ENV NEXT_PUBLIC_API_URI=${NEXT_PUBLIC_API_URI}
COPY . .
RUN npm i
RUN npm run build
EXPOSE 3000
EXPOSE 80
CMD ["npm", "run", "serve"]
You would only need to use |
Beta Was this translation helpful? Give feedback.
-
|
A simple way to think about this is:
So if you do this: services:
fe:
build: ./
environment:
NEXT_PUBLIC_API_URI: https://api.example.comthat value is too late for client-side If the value is known at image build time, build args are fine: services:
fe:
build:
context: ./
args:
NEXT_PUBLIC_API_URI: https://api.example.comARG NEXT_PUBLIC_API_URI
ENV NEXT_PUBLIC_API_URI=$NEXT_PUBLIC_API_URI
RUN npm run buildBut if the goal is one image for dev/staging/prod, build args are not enough, because they still bake the value into the image. For that runtime case, this is the problem REP is designed for: https://github.com/RuachTech/rep REP does not make Client code: import { rep } from '@rep-protocol/sdk'
const apiUri = rep.get('API_URI')Runtime env: services:
fe:
image: my-next-app:latest
ports:
- "8080:8080"
environment:
REP_PUBLIC_API_URI: https://api.example.com
REP_PUBLIC_ENV_NAME: productionThe REP gateway injects those values into the HTML as inert JSON: <script id="__rep__" type="application/json">...</script>For a standalone Next.js image, the gateway can sit in front of the Next server: NODE_ENV=production node /app/server.js &
exec rep-gateway \
--mode proxy \
--port 8080 \
--upstream localhost:3000Then you can run the same image with different values: docker run --rm -p 8080:8080 \
-e REP_PUBLIC_API_URI=https://api.staging.example.com \
-e REP_PUBLIC_ENV_NAME=staging \
my-next-app:latestdocker run --rm -p 8080:8080 \
-e REP_PUBLIC_API_URI=https://api.example.com \
-e REP_PUBLIC_ENV_NAME=production \
my-next-app:latestSo the short version is:
|
Beta Was this translation helpful? Give feedback.
For build time values you need to use build args instead of environment variables. Here are the updated files: