Search code examples
dockerdockerfilesveltesveltekit

PUBLIC_BACKEND_SERVER_URL is not exported error During Docker Build Despite Being Set in .env File in SvelteKit Project


I'm working on a SvelteKit project and I'm encountering an issue where the PUBLIC_BACKEND_SERVER_URL environment variable, which I have defined in my .env file, is not being recognized during the Docker build process. Here are the details of the error and my setup:

Error log when running docker build -t svelte-frontend .:

2.803 x Build failed in 2.13s
2.803 error during build:
2.803 src/lib/posts/fetch-pagination.ts (3:9): "PUBLIC_BACKEND_SERVER_URL" is not exported by "virtual:$env/static/public", imported by "src/lib/posts/fetch-pagination.ts".
2.803 file: /app/src/lib/posts/fetch-pagination.ts:3:9
2.803 
2.803 1: import { get, type Writable } from "svelte/store";
2.803 2: import { collectionObj } from "./store";
2.803 3: import { PUBLIC_BACKEND_SERVER_URL } from "$env/static/public";
2.803             ^
2.803 

Code:

src/lib/fetch-pagination.ts

import { get, type Writable } from "svelte/store";
import { collectionObj } from "./store";
import { PUBLIC_BACKEND_SERVER_URL } from "$env/static/public";

// Define the options for the fetch request
const options = {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({...}),
};

// Fetch function to get paginated posts
export const fetchPaginatedPosts = async (key: string = "posts", last_id: string = "") => {
  collectionObj.set(key);
  console.log("de: ", get(collectionObj));

  try {
    const response = await fetch(
      `${PUBLIC_BACKEND_SERVER_URL}/get-paginated`,
      options
    );
    if (!response.ok) {
      throw new Error("Network response was not ok");
    }
    const res = await response.json();
    console.log("API call");
    return res;
  } catch (error) {
    console.error(error);
    throw error;
  }
};

.env File:

PUBLIC_BACKEND_SERVER_URL=http://localhost:1234

Dockerfile:

FROM node:20-alpine AS builder

WORKDIR /app
COPY package*.json .
RUN npm ci
COPY . .

RUN npm run build
RUN npm prune --production

FROM node:20-alpine
WORKDIR /app

COPY --from=builder /app/build build/
COPY --from=builder /app/node_modules node_modules/

COPY package.json .

EXPOSE 3000
ENV NODE_ENV=production

CMD ["node", "./build"]

The environment variables load correctly and the application works as expected when I run npm run dev. However, the build fails when trying to build the Docker image.

package.json:

    "scripts": {
        "dev": "vite dev",
        "build": "vite build",
        "preview": "vite preview",
        "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
        "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
    },

Questions:

  1. Why is PUBLIC_BACKEND_SERVER_URL not being recognized by $env/static/public during the Docker build process?
  2. Are there additional steps I need to take to ensure environment variables are properly imported during a Docker build in a SvelteKit project?
  3. Is there something wrong with my Dockerfile setup that might be causing this issue?

Any insights or suggestions would be greatly appreciated. Thank you!

Edit ✅:

I have been wondering why I couldn't copy .env; every time when i tried to copy .env i failed.

Turns out i had **/.env on .dockerignore. While it is a good practice to igonre .env, but if you encouter the same error, please make sure if you accidentally included a file you intended to copy on Dockerfile.


Solution

  • In my node environment (without docker) you have to run the production build with a special module enabled in order to load .env files. They aren't loaded in prod by default, but they are in dev

    https://kit.svelte.dev/docs/adapter-node#environment-variables

    node -r dotenv/config build
    

    or node v20.6+

    node --env-file=.env build