|
15 | 15 | - [Docker Run](#docker-run) |
16 | 16 | - [Security](#security) |
17 | 17 | - [node-gyp alpine](#node-gyp-alpine) |
18 | | -- [Multi-architecture images](#multi-architecture-images) |
19 | 18 | - [Smaller images without npm/yarn](#smaller-images-without-npmyarn) |
20 | 19 |
|
21 | 20 | <!-- END doctoc generated TOC please keep comment here to allow auto update --> |
@@ -181,24 +180,12 @@ FROM node:alpine as app |
181 | 180 | COPY --from=builder node_modules . |
182 | 181 | ``` |
183 | 182 |
|
184 | | -## Multi-architecture images |
185 | | - |
186 | | -A dependency tree installed once cannot serve two architectures. `docker buildx build` with |
187 | | -`--platform linux/amd64,linux/arm64` builds each stage natively per platform, but if one stage runs |
188 | | -`npm ci` on the build host and a later stage copies the result with |
189 | | -`COPY --from=builder node_modules .`, that same tree - carrying the build host's prebuilt native |
190 | | -addons - ends up inside every platform tag. The manifest still advertises both architectures, so nothing |
191 | | -looks wrong until an arm64 host loads an x86-64 binary: |
192 | | - |
193 | | -```console |
194 | | -Error: /app/node_modules/better-sqlite3/build/Release/better_sqlite3.node: invalid ELF header |
195 | | -``` |
196 | | - |
197 | | -Install dependencies inside each platform's stage (or rebuild them there with `npm rebuild`), and |
198 | | -publish only the architectures actually built. To check an image that is already published, without a |
199 | | -Docker engine: fetch its manifest from the registry, decompress the layer tarballs, and read the |
200 | | -`e_machine` field of any `.node` file - two bytes at offset 18, `0x3e` for x86-64 and `0xb7` for |
201 | | -AArch64. |
| 183 | +Note that this multistage pattern only produces a tree that works on the architecture the builder ran on. |
| 184 | +Native addons are compiled or downloaded for that host, so `COPY --from=builder node_modules .` into a stage |
| 185 | +built for a different architecture puts a mismatched binary in the image while the manifest still looks |
| 186 | +correct, and the first `require()` of it fails with `invalid ELF header`. Under |
| 187 | +`docker buildx build --platform linux/amd64,linux/arm64`, install or `npm rebuild` inside each platform's |
| 188 | +stage instead of sharing one tree between them. |
202 | 189 |
|
203 | 190 | ## Smaller images without npm/yarn |
204 | 191 |
|
|
0 commit comments