Replies: 5 comments 2 replies
|
env variables are exposed in export default defineConfig({
define: {
__SYSTEMENV__: JSON.stringify(process.env),
},
plugins: [sveltekit()],
});At which point I could read env variables by accessing |
|
The reason this happens is timing. Cloud Run sets environment variables when the container starts. But Vite has already built the frontend before that: RUN npm run buildAt that point Vite replaces One way to solve this is to move browser config out of Vite build-time replacement and into runtime injection. REP is built for that flow: https://github.com/RuachTech/rep Instead of: const apiUrl = import.meta.env.VITE_API_URLuse: import { rep } from '@rep-protocol/sdk'
const apiUrl = rep.get('API_URL')Then set the value in Cloud Run as: REP_PUBLIC_API_URL=https://api.example.com
REP_PUBLIC_ENV_NAME=productionThe gateway reads those env vars when the container starts and injects them into HTML as inert JSON: <script id="__rep__" type="application/json">...</script>For a Vite app, the Dockerfile can be simplified to let the gateway serve the static files directly: FROM node:22-alpine AS build
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build
FROM scratch
COPY --from=ghcr.io/ruachtech/rep/gateway:latest /usr/local/bin/rep-gateway /rep-gateway
COPY --from=build /app/dist /static
EXPOSE 8080
ENTRYPOINT ["/rep-gateway", "--mode", "embedded", "--static-dir", "/static", "--port", "8080"]Build once: docker build -t my-vite-app:latest .Run locally with runtime config: docker run --rm -p 8080:8080 \
-e REP_PUBLIC_API_URL=https://api.example.com \
-e REP_PUBLIC_ENV_NAME=production \
my-vite-app:latestDeploy the same image to Cloud Run and set the same The important distinction is:
Also, be careful with REP_PUBLIC_* # browser-visible
REP_SENSITIVE_* # encrypted browser-delivered values
REP_SERVER_* # never sent to the browser |
|
Environment variables set in Google Cloud Run are available at runtime ( RUN npm run build # <-- env vars don't exist yet hereVite replaces Fix 1 — Pass env vars at build time using FROM node:14-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
ARG VITE_API_URL
ENV VITE_API_URL=$VITE_API_URL
RUN npm run buildThen build with: docker build --build-arg VITE_API_URL=https://your-api.com .Fix 2 — Use runtime config instead of Vite env vars: Serve a // At app startup
const config = await fetch('/config.json').then(r => r.json());This way the config comes from Cloud Run's runtime environment, not from build-time substitution. Fix 3 — Use export default defineConfig({
define: {
__API_URL__: JSON.stringify(process.env.API_URL),
},
});But this still requires the env var during build. For true runtime config on a static frontend, Fix 2 is the right approach. |
|
This is a very common Vite + Docker gotcha: Vite inlines environment variables at build time, not at runtime. When you run When Cloud Run sets environment variables on the container, those variables exist in the container process ( Three solutions: Option 1 — Pass build args to Docker (simplest for Cloud Run) # Dockerfile
FROM node:14-alpine as build
ARG VITE_API_URL # declare the build-time arg
ENV VITE_API_URL=$VITE_API_URL # expose it to Vite as env var
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build# Build command
docker build --build-arg VITE_API_URL=https://api.example.com -t myapp .In Cloud Run, set these as build-time values via Cloud Build substitution variables, not Cloud Run env vars. Option 2 — Generate a runtime config file with an entrypoint script Serve a # docker-entrypoint.sh
#!/bin/sh
cat > /usr/share/nginx/html/config.js << EOF
window.__ENV__ = {
VITE_API_URL: "${VITE_API_URL}",
VITE_OTHER_VAR: "${VITE_OTHER_VAR}"
};
EOF
nginx -g "daemon off;"<!-- index.html -->
<script src="/config.js"></script>Then use Option 3 — Use a backend/SSR layer to serve the HTML with injected values, but this changes your architecture significantly. Option 2 is the most flexible for Cloud Run since it lets runtime env vars flow through to the frontend without rebuilding the image. |
|
This is a classic Vite + Docker timing mismatch. The root cause is straightforward once you see it. What's actually happening Your Dockerfile runs When Google Cloud Run starts your container and sets environment variables, those variables are available to the running process (nginx or Node.js), but they're not available to the browser. The browser just downloads static files from nginx — there's no Node.js runtime in the browser, no So Cloud Run can have the perfect env vars configured, but the already-compiled JS in your Fix 1 — Pass env vars at Docker build time (simplest) Use Docker FROM node:14-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
# Declare build args
ARG VITE_API_URL
ARG VITE_OTHER_VAR
# Expose them as env vars for Vite's build step
ENV VITE_API_URL=$VITE_API_URL
ENV VITE_OTHER_VAR=$VITE_OTHER_VAR
RUN npm run build
FROM fholzer/nginx-brotli:v1.12.2
WORKDIR /etc/nginx
ADD nginx.conf /etc/nginx/nginx.conf
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]Build it with: In Cloud Build, pass these as substitution variables, not Cloud Run runtime env vars — they need to exist at image build time, not container start time. Fix 2 — Runtime injection via entrypoint script (same image, multiple environments) If you want one image that can be deployed to staging and production with different configs, generate a #!/bin/sh
# docker-entrypoint.sh
cat > /usr/share/nginx/html/config.js << EOF
window.__ENV__ = {
VITE_API_URL: "${VITE_API_URL}",
};
EOF
exec nginx -g "daemon off;"Add it to <script src="/config.js"></script>Then in your app: // instead of import.meta.env.VITE_API_URL
const apiUrl = window.__ENV__.VITE_API_URL;Now Cloud Run sets Which to use?
|
Uh oh!
There was an error while loading. Please reload this page.
Hi guys!
I am deploying the application through docker and I have added all the required environment variables manually in google cloud run, but they aren't accessible in the deployed website. I have logged them in the front end and it is showing undefined.
Here is the docker file that I am using:
FYI, the docker is working fine locally and the environments are being read as well. It is just google cloud that isn't reading them.
All reactions