#Astro SSR with Docker not reading enviroment variables in client side

19 messages · Page 1 of 1 (latest)

oak atlas
#

When using Docker+Astro+Bun my env variable from .env can be read without docker using import.meta.env.PUBLIC_API_URL
but when using docker import.meta.env does not have PUBLIC_API_URL and process.env is undefined
this is my dockerfile

FROM oven/bun:canary-debian as base
WORKDIR /app

FROM base AS install
USER root

COPY ./package.json ./bun.lockb ./astro.config.mjs ./postcss.config.js ./tailwind.config.js ./tsconfig.json ./
COPY ./src ./src
COPY ./public ./public

# Install dependencies
RUN bun install

FROM base AS release
USER root

COPY --from=install /app/ .
RUN bunx --bun astro build

ENV HOST=0.0.0.0
ENV PORT=4321
EXPOSE 4321
# CMD bunx astro dev
CMD bun run ./dist/server/entry.mjs

this is how I try to obtain my variable in a <script> tag

const API_URL = import.meta.env["PUBLIC_API_URL"] || process.env["PUBLIC_API_URL"];
console.log('API_URL', API_URL);
#

side note: the variable can be read in server side code --- --- using Bun.env.PUBLIC_API_URL

sterile mountain
#

We currently have awkward rules where...

  • astro-provided variables (import.meta.env.MODE, PROD, BASE_URL, DEV, SITE, ASSETS_PREFIX) are always inlined

  • variables found in .env file are inlined when used as import.meta.env.XYZ

  • ...unless they are also available in process.env, in which case import.meta.env.XYZ is replaced in the compiled code with process.env.XYZ

  • only variables prefixed with PUBLIC_ are inlined for client-side code

  • if XYZ is neither in an .env file nor in the environment at the time of building, import.meta.env.XYZ will always be undefined at runtime

#

we don't do anything special with process.env or Bun.env, so it will always show the values in the environment at the time the code is run, not giving any special treatment means values from an .env file will not appear on there since node doesn't read it (although you can pass --env-file in recent versions)

#

with that unnecessarily long (we are fixing it) background out of the way...

#

i see that you are using process.env in a script tag, this will become problematic since code within script tags only ever gets executed in the browser, and they don't have the process global

#

the use of the square bracket syntax would be problematic because import.meta.env may be read directly from source code, maybe the result is different if it is import.meta.env.PUBLIC_API_URL instead

#

most importantly, you would also need to copy .env file into the docker builder, which it seems gets missed when other config files are being copied

oak atlas
#

but how would I deploy it?

#

because my gitignore is ignoring the .env file

#

and doesn't sound secure to put my secret variables in github

sterile mountain
#

if you consider them secret, you wouldn't want to use them within a script tag either

#

anyone can read client-side js

oak atlas
#

ok I managed to solve it by making the build in the same CMD as the run command because enviroment variables in docker are not defined during build time but they are in run time, so I moved the astro build and run into docker runtime (CMD)
hope that makes sense

CMD bunx --bun astro build && bun run ./dist/server/entry.mjs

also it has the desired effect of not exposing all the enviroment variables but only the ones I use

# .env
PUBLIC_API_URL=https://lat-$$$.com
SECRET=ASDASD
ANOTHER_SECRET=ASDASD2
sterile mountain
#

does that mean the image will build your project every time a container is started?

oak atlas
#

sadly yes

#

but building takes 2-5 seconds so its not a big deal for now

sterile mountain
#

oh wow

#

thats awesome