a month ago
I have separate Dockerfiles to build my API and Frontend as I achieved this approach as the most suitable for my case. The thing is, since I'm using a custom Dockerfile, I need to access the environment variables from Railway and I try adding them as ARGs and ENVs in both building and running steps, but still fails when the server is ran.
I've followed the documentation and read other threads but none seem to clarify what am I doing wrong. I'm using Bun and Turborepo set to loose
Repository: https://github.com/pulgueta/virtualpot
This is one of my Dockerfiles:
ARG BUN_VERSION=1
ARG PORT
ARG HOSTNAME
ARG FRONTEND_URL
FROM oven/bun:${BUN_VERSION} AS deps
WORKDIR /app
COPY package.json bun.lock turbo.json ./
COPY apps/api/package.json ./apps/api/package.json
RUN bun install
FROM oven/bun:${BUN_VERSION} AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/apps/api/node_modules ./apps/api/node_modules
COPY . .
ENV PORT=$PORT
ENV HOSTNAME=$HOSTNAME
ENV FRONTEND_URL=$FRONTEND_URL
RUN bun run build --filter=@virtualpot/api
FROM oven/bun:${BUN_VERSION}-slim AS runner
WORKDIR /app
COPY --from=builder /app/apps/api/dist ./dist
ENV NODE_ENV=production
ENV PORT=$PORT
ENV HOSTNAME=$HOSTNAME
ENV FRONTEND_URL=$FRONTEND_URL
EXPOSE $PORT
CMD ["bun", "run", "dist/index.js"]Pinned Solution
a month ago
Glad it worked- I'm not familiar with @t3-oss so I can't answer that piece.
That said,I do know Vite injects environment variables at build time so they are needed during the build phase of your web app
This is because they just get bundled into the build and shipped to the client 
4 Replies
a month ago
Ahhh, the problem is that ARG doesn't persist across different build stages. Your ARG declarations at the top aren't being passed through to the final image.
Try something like this:
ARG BUN_VERSION=1
FROM oven/bun:${BUN_VERSION} AS deps
WORKDIR /app
COPY package.json bun.lock turbo.json ./
COPY apps/api/package.json ./apps/api/package.json
RUN bun install
FROM oven/bun:${BUN_VERSION} AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/apps/api/node_modules ./apps/api/node_modules
COPY . .
RUN bun run build --filter=@virtualpot/api
FROM oven/bun:${BUN_VERSION}-slim AS runner
WORKDIR /app
COPY --from=builder /app/apps/api/dist ./dist
ENV NODE_ENV=production
# Railway will inject PORT, HOSTNAME, FRONTEND_URL, etc at runtme
# No need to set them here; ONLY set variables that way that are needed by the build step
EXPOSE 3000
CMD ["bun", "run", "dist/index.js"]If you actually need build time variables in a stage, you'll need to copy/paste them into each stage that needs those variables during the build.
mykal
Ahhh, the problem is that ARG doesn't persist across different build stages. Your ARG declarations at the top aren't being passed through to the final image. Try something like this:ARG BUN_VERSION=1 FROM oven/bun:${BUN_VERSION} AS deps WORKDIR /app COPY package.json bun.lock turbo.json ./ COPY apps/api/package.json ./apps/api/package.json RUN bun install FROM oven/bun:${BUN_VERSION} AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/apps/api/node_modules ./apps/api/node_modules COPY . . RUN bun run build --filter=@virtualpot/api FROM oven/bun:${BUN_VERSION}-slim AS runner WORKDIR /app COPY --from=builder /app/apps/api/dist ./dist ENV NODE_ENV=production # Railway will inject PORT, HOSTNAME, FRONTEND_URL, etc at runtme # No need to set them here; ONLY set variables that way that are needed by the build step EXPOSE 3000 CMD ["bun", "run", "dist/index.js"]If you actually need build time variables in a stage, you'll need to copy/paste them into each stage that needs those variables during the build.
a month ago
Holy, that worked, thanks! Sadly, it didn't work out for my TanStack Start app, I have both commands as suggested in many places:
"build": "bun --bun vite build",
"start": "bun run .output/server/index.mjs"ARG BUN_VERSION=1-alpine
FROM oven/bun:${BUN_VERSION} AS builder
# ...previous steps
RUN bun run build
FROM oven/bun:${BUN_VERSION} AS runner
WORKDIR /app
COPY --from=builder /app/apps/web/.output /app/.output
ENV NODE_ENV=production
CMD ["bun", "run", ".output/server/index.mjs"]
Dockerfile is pretty much almost the same, the VITE_API_URL is set but the @t3-oss/env-core package throws an error when I enter the page saying it's missing the environment variables. Do these need to be used at build time?
pulgueta
Holy, that worked, thanks! Sadly, it didn't work out for my TanStack Start app, I have both commands as suggested in many places:"build": "bun --bun vite build", "start": "bun run .output/server/index.mjs"ARG BUN_VERSION=1-alpine FROM oven/bun:${BUN_VERSION} AS builder # ...previous steps RUN bun run build FROM oven/bun:${BUN_VERSION} AS runner WORKDIR /app COPY --from=builder /app/apps/web/.output /app/.output ENV NODE_ENV=production CMD ["bun", "run", ".output/server/index.mjs"]Dockerfile is pretty much almost the same, the VITE_API_URL is set but the @t3-oss/env-core package throws an error when I enter the page saying it's missing the environment variables. Do these need to be used at build time?
a month ago
Glad it worked- I'm not familiar with @t3-oss so I can't answer that piece.
That said,I do know Vite injects environment variables at build time so they are needed during the build phase of your web app
This is because they just get bundled into the build and shipped to the client 
mykal
Glad it worked- I'm not familiar with @t3-oss so I can't answer that piece.That said,I do know Vite injects environment variables at build time so they are needed during the build phase of your web appThis is because they just get bundled into the build and shipped to the client
a month ago
It definitely worked! It's now just a matter of networking to stick all the pieces together. Thanks a lot!
Status changed to Solved brody • about 1 month ago