Skip to content

Commit e8b7ddc

Browse files
authored
fix(docker): install node-gyp toolchain in build stage for blocked prebuilt downloads (#2148)
better-sqlite3 installs via `prebuild-install || node-gyp rebuild`. The prebuilt binary is fetched from GitHub Releases, which corporate proxies and offline mirrors commonly block. The fallback then compiles from source and dies in node:22-slim because no compiler toolchain is present. Install python3/make/g++ in the deps stage only; the runtime image starts from a fresh node:22-slim and is unaffected. Also documents the same failure mode in the Node.js deployment guide and clarifies that the guide's Dockerfile (single site) and the repo-root Dockerfile (monorepo) are different scenarios. Follow-up to #2132 (#2118).
1 parent e2c7549 commit e8b7ddc

2 files changed

Lines changed: 34 additions & 0 deletions

File tree

Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ WORKDIR /app
66
# ---- Install dependencies ----
77
FROM base AS deps
88

9+
# Toolchain for the node-gyp fallback of native deps. better-sqlite3 installs
10+
# via `prebuild-install || node-gyp rebuild`; the prebuilt binary comes from
11+
# GitHub Releases, which corporate proxies and offline mirrors commonly block.
12+
# The fallback then compiles from source and needs python3/make/g++, which
13+
# node:22-slim doesn't ship. Build stages only -- the runtime image below
14+
# starts from a fresh node:22-slim and is unaffected.
15+
RUN apt-get update \
16+
&& apt-get install -y --no-install-recommends python3 make g++ \
17+
&& rm -rf /var/lib/apt/lists/*
18+
919
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
1020
# pnpm-workspace.yaml declares patchedDependencies -> patches/, which pnpm
1121
# reads during install. It must be in the deps stage or --frozen-lockfile

docs/src/content/docs/deployment/nodejs.mdx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,30 @@ CMD ["node", "./dist/server/entry.mjs"]
117117

118118
The seed file is read at build time and inlined into the bundle, so it does not need to be copied into the runtime image. Migrations run on the first request after a deploy; the seed applies only when the database has no collections and setup hasn't been completed — existing data is never overwritten.
119119

120+
<Aside>
121+
This Dockerfile builds **your own EmDash site** — a project that has `emdash` as a dependency. It is
122+
not interchangeable with the `Dockerfile` in the root of the EmDash repository, which builds the whole
123+
pnpm monorepo and packages the blog template from source.
124+
</Aside>
125+
126+
<Aside type="caution" title="Native dependencies behind restrictive networks">
127+
EmDash's SQLite driver (`better-sqlite3`) installs a prebuilt binary downloaded from GitHub Releases.
128+
If your build environment blocks that download (corporate proxy, offline mirror), the install falls
129+
back to compiling from source and fails with a `gyp ERR! find Python` error, because slim/alpine Node
130+
images ship no compiler toolchain.
131+
</Aside>
132+
133+
If you hit that error, install the toolchain in the builder stage before `npm ci`:
134+
135+
```dockerfile
136+
# Alpine-based images (node:22-alpine)
137+
RUN apk add --no-cache python3 make g++
138+
139+
# Debian-based images (node:22-slim)
140+
RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ \
141+
&& rm -rf /var/lib/apt/lists/*
142+
```
143+
120144
Build the image and run the container:
121145

122146
```bash

0 commit comments

Comments
 (0)