Skip to content

Docker

Vite+ 提供了一个官方 Docker 镜像,并预装了 vp CLI:

bash
ghcr.io/voidzero-dev/vite-plus

可用于构建、CI 和 devcontainer。它不适合作为生产运行时镜像。

vp 会从你的项目中解析 Node.js 版本(.node-versiondevEngines.runtimeengines.node),并在安装/构建期间下载该确切版本。 这意味着该镜像不需要特定于 Node 版本的标签。

对于生产环境,请使用多阶段构建:用 Vite+ 镜像构建应用,然后仅将解析出的 Node.js 二进制文件、构建产物和生产依赖复制到更小的运行时镜像中。

镜像标签

标签跟踪 vp 版本:

标签含义
ghcr.io/voidzero-dev/vite-plus:latest最新发布版
ghcr.io/voidzero-dev/vite-plus:<major>最新主版本
ghcr.io/voidzero-dev/vite-plus:<major>.<minor>最新次版本
ghcr.io/voidzero-dev/vite-plus:<major>.<minor>.<patch>精确版本

这些示例使用 :latest 来跟踪最新发布版本;如果你需要可复现的构建,请固定到确切的标签或摘要。该镜像为 linux/amd64linux/arm64 发布,并且默认以非 root 的 vp 用户运行。该用户拥有免密码的 sudo,因此需要 root 权限的构建/CI 步骤(额外的 apt 包、playwright install --with-deps)无需更改镜像用户即可正常工作。

GitHub 包页面 浏览所有已发布的版本和摘要。

生产环境:SSR / Node.js 服务端应用

对于在生产环境中运行 Node.js 的应用(SvelteKit、Nuxt、自定义的 Vite SSR 服务器等),请使用工具链镜像进行构建,并将解析后的 Node.js 以及构建产物复制到一个精简的运行时阶段中:

Dockerfile
dockerfile
# syntax=docker/dockerfile:1

# --- build stage: the official Vite+ toolchain image ---
FROM ghcr.io/voidzero-dev/vite-plus:latest AS build
WORKDIR /app

# 先安装依赖,这样当源代码变更时,这一层可以被缓存。
COPY --chown=vp:vp package.json pnpm-lock.yaml pnpm-workspace.yaml .node-version* ./
RUN vp install --frozen-lockfile

# 构建。vp 会读取 .node-version,并自动提供那个确切版本的 Node.js。
COPY --chown=vp:vp . .
RUN vp build

# 为运行时阶段导出确切解析后的 Node.js 二进制文件。
RUN cp "$(vp env which node | head -1)" /tmp/node

# --- deps stage: production-only dependencies ---
# 单独进行一次全新的 `--prod` 安装,这样 devDependencies(包括 vite-plus
# 工具链)就会被排除。若在上面的完整安装后同一阶段再运行 `--prod`,
# 已经安装好的 devDependencies 不会被清理掉。
FROM ghcr.io/voidzero-dev/vite-plus:latest AS deps
WORKDIR /app
COPY --chown=vp:vp package.json pnpm-lock.yaml pnpm-workspace.yaml .node-version* ./
RUN vp install --frozen-lockfile --prod

# --- runtime stage: small, glibc, no vp ---
FROM debian:bookworm-slim AS runtime
WORKDIR /app
ENV NODE_ENV=production

# 来自 .node-version 的确切 Node.js(官方、经过签名验证的构建)。
COPY --from=build /tmp/node /usr/local/bin/node

COPY --from=build /app/dist ./dist
COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/package.json ./

USER nobody
EXPOSE 3000
CMD ["node", "dist/server.js"]

部署后的镜像只包含 Node.js、你的应用以及生产依赖,并且会严格匹配 .node-version。 它比默认的 node:* 镜像小得多;关于最小体积的结果,请参见下面的 distroless 提示。

在单独的阶段中裁剪生产依赖

如上所示,请在独立的 deps 阶段中安装生产依赖。在同一阶段中先执行完整的 vp install, 再执行 vp install --prod,不会移除已经安装的 devDependencies,因此 vite-plus 工具链也会被复制到运行时镜像中。如果你的服务端打包是完全自包含的(没有未打包的运行时依赖), 则可以完全跳过复制 node_modules

更小一些

如果想要一个不带 shell、CVE 更少的最小运行时,可将运行时基础镜像替换为 distroless (gcr.io/distroless/cc),并保持 ENTRYPOINT 使用向量形式。它基于 glibc, 因此复制过去的 Node.js 二进制文件仍然兼容。

生产环境:静态 SPA / SSG

静态站点在运行时不需要 Node.js;使用任意静态 服务器提供构建输出即可:

Dockerfile
dockerfile
FROM ghcr.io/voidzero-dev/vite-plus:latest AS build
WORKDIR /app
COPY --chown=vp:vp package.json pnpm-lock.yaml pnpm-workspace.yaml .node-version* ./
RUN vp install --frozen-lockfile
COPY --chown=vp:vp . .
RUN vp build

FROM nginx:alpine AS runtime
COPY --from=build /app/dist /usr/share/nginx/html

持续集成

在基于容器的 CI(GitLab CI、Buildkite、CircleCI、 Jenkins 等)中直接使用该镜像:

.gitlab-ci.yml
yaml
build:
  image: ghcr.io/voidzero-dev/vite-plus:latest
  script:
    - vp install --frozen-lockfile
    - vp check
    - vp test
    - vp build

在 GitHub Actions 中,建议使用 setup-vp 而不是该镜像。

浏览器模式测试(Vitest / Playwright)

以非 root 的 vp 用户运行是浏览器所需要的:Chromium 会保留 其沙箱(以 root 运行浏览器会禁用它)。在作业中安装浏览器及其 系统库。playwright install --with-deps 需要 root 来 apt-get install 这些库。vp 用户拥有免密码的 sudo,因此 Playwright 会使用它来安装这些库,而无需更改镜像用户:

.gitlab-ci.yml
yaml
test:
  image: ghcr.io/voidzero-dev/vite-plus:latest
  script:
    - vp install --frozen-lockfile
    - vp exec playwright install --with-deps chromium
    - vp test

vp exec 运行的是项目自己的 Playwright(来自你的 lockfile),因此它会安装 你的测试所期望的浏览器版本。优先使用它,而不是 vpx playwright install, 后者会下载最新的 Playwright,并且可能获取不同的 浏览器版本。

如果想把浏览器及其库构建进派生镜像,而不是在每次运行时都安装它们, 请先安装项目依赖,这样构建进去的浏览器就会与你的 lockfile 匹配,然后使用项目的 Playwright 进行安装(可通过 sudo 使用 root):

Dockerfile
dockerfile
FROM ghcr.io/voidzero-dev/vite-plus:latest
WORKDIR /app
COPY --chown=vp:vp package.json pnpm-lock.yaml pnpm-workspace.yaml .node-version* ./
RUN vp install --frozen-lockfile
RUN vp exec playwright install --with-deps chromium

如果 Chromium 在 CI 负载下崩溃,请使用 --ipc=host 为容器提供更多共享内存;请参阅 Playwright Docker 文档

Devcontainers

Use this image as a ready-to-use development container, with the toolchain preinstalled:

.devcontainer/devcontainer.json
jsonc
{
  "image": "ghcr.io/voidzero-dev/vite-plus:latest",
}

临时使用

在不将 vp 安装到本机的情况下,对项目运行任意 vp 命令:

bash
docker run --rm -it -v "$PWD:/app" -w /app ghcr.io/voidzero-dev/vite-plus vp build

备注

  • Node.js 版本:在构建时从 .node-versionengines.nodedevEngines.runtime 提供,因此没有特定于 Node.js 的镜像标签。依赖项的 COPY 使用 .node-version* 通配符,所以该文件是可选的:通过 engines.node/devEngines.runtime 固定版本的项目不需要 .node-version, 而使用该文件的项目在每个阶段都可以使用它。
  • 非 root 用户:镜像以非 root 的 vp 用户运行,因此请像示例中那样使用 COPY --chown=vp:vp ... 复制源代码。否则,COPY 会写入由 root 拥有的文件, 而 vp install 无法更新这些文件(权限被拒绝)。vp 用户拥有无密码的 sudo, 以便在偶尔需要 root 的步骤中使用(安装额外的 apt 包或 playwright install --with-deps), 因此你很少需要切换镜像用户。生产运行时阶段是一个独立的、没有 vp 的基础镜像, 所以这种便利不会出现在你部署后的镜像中。
  • 原生插件:镜像包含 C/C++ 构建工具链(build-essentialpython3),因此像 better-sqlite3 这样的原生依赖会在 vp install 期间编译。
  • glibc:该镜像基于 glibc,因此使用官方、经过签名验证的 Node.js 构建版本。
  • 自定义基础镜像:如果要向你自己的基础镜像中添加 vp,请运行安装器: curl -fsSL https://vite.plus | bash(设置 VP_VERSION 以固定版本)。