Files
vercel__next.js/scripts/native-builder.Dockerfile
Jimmy Miller e928f2395f Migrate napi-rs bindings from v2 to v3 (#95412)
Draft PR for testing

<!-- NEXT_JS_LLM_PR -->
2026-08-13 11:35:52 -04:00

121 lines
6.3 KiB
Docker
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Multi-stage Dockerfile for building Next.js native binaries (next-swc).
#
# Produces a single image that can cross-compile ALL 4 Linux targets
# (x86_64/aarch64 × gnu/musl) from either an x86_64 or aarch64 host.
#
# Build:
# docker build -t next-swc-builder:latest -f scripts/native-builder.Dockerfile .
#
# The image includes:
# - Ubuntu 20.04 (glibc 2.31 — broad compatibility baseline)
# - Clang/LLD for all compilation and linking via --target
# - GNU cross-sysroots via crossbuild-essential (Ubuntu multiarch)
# - musl sysroots from GHCR-hosted rust-musl-cross images
# - Node.js 20 (glibc-linked, used as build tool for all targets)
# - Rust nightly toolchain (pinned to match rust-toolchain.toml)
# - @napi-rs/cli for building native Node.js addons
FROM ghcr.io/rust-cross/rust-musl-cross:x86_64-musl@sha256:bcf6a66615f9d5bae659e38ab4311260e0488d1c34ad0ab9f9147f4cd5ef64ed AS musl_x86_64
FROM ghcr.io/rust-cross/rust-musl-cross:aarch64-musl@sha256:eab6a58ff66eaa33fa87fc31ed11403596719ca3f23aa51626fb993d77c1200b AS musl_aarch64
FROM ubuntu:20.04 AS builder
# Avoid interactive prompts during apt-get
ENV DEBIAN_FRONTEND=noninteractive
# Enable multiarch for cross-compilation sysroots.
# Write sources.list from scratch with explicit [arch=...] tags.
# On arm64 hosts: native packages from ports, foreign amd64 from archive.
# On amd64 hosts: native packages from archive, foreign arm64 from ports.
RUN HOST_ARCH=$(dpkg --print-architecture) && \
if [ "$HOST_ARCH" = "arm64" ]; then \
NATIVE_MIRROR="http://ports.ubuntu.com/ubuntu-ports"; FOREIGN_ARCH=amd64; \
FOREIGN_MIRROR="http://archive.ubuntu.com/ubuntu"; \
else \
NATIVE_MIRROR="http://archive.ubuntu.com/ubuntu"; FOREIGN_ARCH=arm64; \
FOREIGN_MIRROR="http://ports.ubuntu.com/ubuntu-ports"; \
fi && \
dpkg --add-architecture "$FOREIGN_ARCH" && \
printf '%s\n' \
"deb [arch=${HOST_ARCH}] ${NATIVE_MIRROR} focal main universe" \
"deb [arch=${HOST_ARCH}] ${NATIVE_MIRROR} focal-updates main universe" \
"deb [arch=${HOST_ARCH}] ${NATIVE_MIRROR} focal-security main universe" \
"deb [arch=${FOREIGN_ARCH}] ${FOREIGN_MIRROR} focal main universe" \
"deb [arch=${FOREIGN_ARCH}] ${FOREIGN_MIRROR} focal-updates main universe" \
"deb [arch=${FOREIGN_ARCH}] ${FOREIGN_MIRROR} focal-security main universe" \
> /etc/apt/sources.list
# Core build tools + GNU cross-compilation sysroots.
# crossbuild-essential installs headers + libs in the multiarch layout
# that clang finds via --target. Both archs installed so the image
# works on either host architecture.
RUN apt-get update && apt-get install -y --no-install-recommends \
curl ca-certificates \
clang lld llvm pkg-config wget git xz-utils libssl-dev \
crossbuild-essential-amd64 crossbuild-essential-arm64 \
&& rm -rf /var/lib/apt/lists/*
# Node.js 20 (glibc-linked, used as a build tool for all targets).
# Installed from the official nodejs.org static tarball rather than via
# NodeSource: the tarball bundles npm and corepack and does not depend on
# NodeSource's apt repo or GPG key server, which has intermittently returned
# HTTP 403 from CI runners. When the key import failed, the NodeSource setup
# script exited 0, so `apt-get install nodejs` silently fell back to Ubuntu's
# stock nodejs package (which does not bundle npm), breaking later npm steps.
ARG NODE_VERSION=20.20.2
RUN case "$(dpkg --print-architecture)" in \
amd64) NODE_ARCH=x64 ;; \
arm64) NODE_ARCH=arm64 ;; \
*) echo "unsupported host architecture: $(dpkg --print-architecture)" >&2; exit 1 ;; \
esac && \
curl -fsSLo /tmp/node.tar.xz \
"https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" && \
tar -xJf /tmp/node.tar.xz -C /usr/local --strip-components=1 \
--exclude CHANGELOG.md --exclude LICENSE --exclude README.md && \
rm /tmp/node.tar.xz && \
node --version && npm --version
# Import prebuilt musl sysroots from the rust-musl-cross images and stage them
# under /opt/*-cross for docker-native-build.sh. The symlinks provide the
# target names that our clang --sysroot flags use, and libgcc/crt objects are
# copied into the sysroot lib dir so clang/rust-lld can find them while linking.
COPY --from=musl_x86_64 /usr/local/musl /opt/x86_64-linux-musl-cross
COPY --from=musl_aarch64 /usr/local/musl /opt/aarch64-linux-musl-cross
RUN ln -s x86_64-unknown-linux-musl /opt/x86_64-linux-musl-cross/x86_64-linux-musl && \
ln -s aarch64-unknown-linux-musl /opt/aarch64-linux-musl-cross/aarch64-linux-musl && \
cp /opt/x86_64-linux-musl-cross/lib/gcc/x86_64-unknown-linux-musl/*/crt*.o \
/opt/x86_64-linux-musl-cross/lib/gcc/x86_64-unknown-linux-musl/*/libgcc.a \
/opt/x86_64-linux-musl-cross/x86_64-linux-musl/lib/ && \
cp /opt/aarch64-linux-musl-cross/lib/gcc/aarch64-unknown-linux-musl/*/crt*.o \
/opt/aarch64-linux-musl-cross/lib/gcc/aarch64-unknown-linux-musl/*/libgcc.a \
/opt/aarch64-linux-musl-cross/aarch64-linux-musl/lib/
# Install Rust — pinned nightly from rust-toolchain.toml
# The COPY of rust-toolchain.toml ensures the image rebuilds when the toolchain changes.
COPY rust-toolchain.toml /tmp/rust-toolchain.toml
RUN TOOLCHAIN=$(grep 'channel' /tmp/rust-toolchain.toml | sed 's/.*"\(.*\)".*/\1/') && \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \
sh -s -- -y --default-toolchain "$TOOLCHAIN" --profile minimal && \
rm /tmp/rust-toolchain.toml
ENV PATH="/root/.cargo/bin:${PATH}"
# Add all 4 Linux rustup targets
RUN rustup target add \
x86_64-unknown-linux-gnu \
aarch64-unknown-linux-gnu \
x86_64-unknown-linux-musl \
aarch64-unknown-linux-musl
# Install cargo-binstall, then use it for Rust tools.
ARG CARGO_BINSTALL_VERSION=1.18.1
RUN ARCH=$(uname -m) && \
curl -fsSL "https://github.com/cargo-bins/cargo-binstall/releases/download/v${CARGO_BINSTALL_VERSION}/cargo-binstall-${ARCH}-unknown-linux-musl.tgz" \
| tar xz -C /root/.cargo/bin && \
npm i -g @napi-rs/cli@3.7.2 && \
cargo binstall --no-confirm --targets "${ARCH}-unknown-linux-musl" cargo-rustflags@0.4.0 && \
cargo binstall --no-confirm --git https://github.com/vercel/sccache sccache && \
node --version && rustc --version && napi -h > /dev/null && cargo rustflags --help > /dev/null && sccache --version
WORKDIR /build