You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SvelteKit Docker构建时PUBLIC_BACKEND_SERVER_URL未导出错误

SvelteKit Docker构建时PUBLIC_环境变量无法识别问题

问题场景

开发SvelteKit项目时,本地执行npm run dev能正常加载.env中定义的PUBLIC_BACKEND_SERVER_URL,但执行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             ^

相关代码与配置

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文件

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"]

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"
    }
}

核心问题

  1. 为什么PUBLIC_BACKEND_SERVER_URL在Docker构建过程中无法被$env/static/public识别?
  2. 在SvelteKit项目的Docker构建中,需要额外执行哪些步骤才能确保环境变量被正确导入?
  3. 我的Dockerfile配置是否存在问题导致了该错误?

问题排查补充(编辑 ✅)

之前尝试复制.env文件失败,最终发现.dockerignore中包含**/.env规则,导致构建时.env文件未被复制到镜像中。虽然忽略.env是安全实践,但如果需要在构建阶段使用该文件,需调整.dockerignore,临时移除该规则,或者通过其他方式注入环境变量。


问题解答

  1. 原因分析:
    SvelteKit/Vite在构建阶段需要读取.env文件中带PUBLIC_前缀的变量,生成virtual:$env/static/public虚拟模块。如果.env文件被.dockerignore排除,无法进入Docker构建上下文,Vite读取不到变量就会报错该变量未导出。本地开发时.env在项目目录下,Vite能正常读取,因此无问题。

  2. 解决步骤:

    • 方法一:调整.dockerignore:临时移除**/.env规则,确保构建时.env被复制到镜像中。注意:生产环境不建议直接复制本地.env,推荐用构建参数注入变量。
    • 方法二:Docker构建参数注入:
      1. 修改Dockerfile,在RUN npm run build前添加:
        ARG PUBLIC_BACKEND_SERVER_URL
        ENV PUBLIC_BACKEND_SERVER_URL=$PUBLIC_BACKEND_SERVER_URL
        
      2. 构建时传入参数:
        docker build --build-arg PUBLIC_BACKEND_SERVER_URL=http://localhost:1234 -t svelte-frontend .
        
    • 方法三:使用.env.production:创建.env.production配置生产环境变量,确保该文件未被.dockerignore排除,构建时Vite会自动读取该文件。
  3. Dockerfile的问题:
    当前Dockerfile本身无语法错误,但缺少环境变量处理逻辑。如果依赖.env文件,必须确保该文件能被复制到构建阶段容器;如果用构建参数,需要添加ARG和ENV声明传递变量到构建阶段。

内容的提问来源于stack exchange,提问作者kawa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 14:22:05