diff --git a/docker/build-env/README.md b/docker/build-env/README.md new file mode 100644 index 000000000..a8b0e4f28 --- /dev/null +++ b/docker/build-env/README.md @@ -0,0 +1,56 @@ +# Build environments + +Dockerfiles that pin the same toolchain CI uses, so a developer can +reproduce a CI build locally without installing platform SDKs on their +workstation. The version pins in each `Dockerfile` must stay in lockstep +with `.github/workflows/`. + +## `android/` + +Mirrors `.github/workflows/mobile-build-validation.yml` (`android_build` +job). Carries Go 1.25.5, Adopt JDK 11, Android cmdline-tools 8512546, +NDK 23.1.7779620 and gomobile pinned at the CI commit. Use it to +produce `netbird.aar` from `./client/android`: + +```bash +docker build -t netbird/build-android docker/build-env/android +docker run --rm -v "$PWD:/src" -w /src netbird/build-android \ + gomobile bind \ + -o netbird.aar \ + -javapkg=io.netbird.gomobile \ + -ldflags="-checklinkname=0 \ + -X golang.zx2c4.com/wireguard/ipc.socketDirectory=/data/data/io.netbird.client/cache/wireguard \ + -X github.com/netbirdio/netbird/version.version=local" \ + ./client/android +``` + +To build the full Android APK, bind-mount the `android-client` repo as +well and run its own `./gradlew assembleDebug` from inside the +container (the gradle wrapper ships with `android-client`). + +## `windows-cross/` + +Cross-compiles Windows binaries from Linux using `mingw-w64`. Lets you +verify that `GOOS=windows go build ./...` compiles cleanly without +needing a Windows VM. Cannot run Windows tests — the `golang-test-windows` +CI job executes on a native `windows-latest` runner with wintun.dll +and PsExec, neither of which lives under Linux containers. + +```bash +docker build -t netbird/build-windows docker/build-env/windows-cross +docker run --rm -v "$PWD:/src" -w /src netbird/build-windows \ + bash -c 'GOOS=windows GOARCH=amd64 go build ./...' +``` + +## What is NOT here + +- **iOS / macOS**: cannot legally run macOS in Docker (Apple EULA), + and Xcode is not redistributable. The `ios_build` CI job uses a + `macos-latest` GitHub runner; locally you need a real Mac. + +- **Native Windows tests**: see note above. The Linux+mingw image + builds, it does not execute Windows-host code paths + (registry, wintun, services, PsExec workflows). + +When CI version pins change, update the corresponding `ARG` lines in +the Dockerfiles and the README's table of versions. diff --git a/docker/build-env/android/Dockerfile b/docker/build-env/android/Dockerfile new file mode 100644 index 000000000..123fc9e02 --- /dev/null +++ b/docker/build-env/android/Dockerfile @@ -0,0 +1,86 @@ +# Android build environment. +# +# Mirrors the toolchain pinned by .github/workflows/mobile-build-validation.yml +# so a `gomobile bind` against ./client/android in this image produces the +# same netbird.aar that CI builds. +# +# Tooling versions (must stay in sync with the CI workflow): +# - Ubuntu 22.04 (matches the ubuntu-latest GitHub runner) +# - Go 1.25.5 (matches go.mod) +# - Adopt JDK 11 (matches actions/setup-java@v3 java-version: 11, distribution: adopt) +# - Android SDK cmdline-tools 8512546 +# - Android NDK 23.1.7779620 +# - gomobile commit v0.0.0-20251113184115-a159579294ab +# +# Usage (from the netbird repo root): +# +# docker build -t netbird/build-android docker/build-env/android +# +# # bind the netbird checkout in and run the same gomobile command CI runs +# docker run --rm -v "$PWD:/src" -w /src netbird/build-android \ +# gomobile bind \ +# -o netbird.aar \ +# -javapkg=io.netbird.gomobile \ +# -ldflags="-checklinkname=0 \ +# -X golang.zx2c4.com/wireguard/ipc.socketDirectory=/data/data/io.netbird.client/cache/wireguard \ +# -X github.com/netbirdio/netbird/version.version=local" \ +# ./client/android +# +# To build the full APK, mount the android-client repo too and run +# `./gradlew assembleDebug` from /android-client (this image carries +# gradle's prerequisites JDK + Android SDK but not the gradle wrapper — +# that ships with android-client). + +FROM ubuntu:22.04 + +ARG DEBIAN_FRONTEND=noninteractive + +# Versions — bump in lockstep with .github/workflows/mobile-build-validation.yml. +ARG GO_VERSION=1.25.5 +ARG ANDROID_CMDLINE_TOOLS_VERSION=8512546 +ARG ANDROID_NDK_VERSION=23.1.7779620 +ARG GOMOBILE_VERSION=v0.0.0-20251113184115-a159579294ab + +ENV ANDROID_HOME=/opt/android-sdk +ENV ANDROID_NDK_HOME=${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION} +ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 +ENV GOPATH=/go +ENV GOTOOLCHAIN=local +ENV CGO_ENABLED=0 +ENV PATH=${GOPATH}/bin:/usr/local/go/bin:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${JAVA_HOME}/bin:${PATH} + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + unzip \ + git \ + openjdk-11-jdk-headless \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +# Install Go (matches go.mod). actions/setup-go fetches the same tarball. +RUN curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" \ + | tar -C /usr/local -xz \ + && go version + +# Install Android SDK command-line tools, accept licenses, install NDK. +RUN mkdir -p "${ANDROID_HOME}/cmdline-tools" \ + && curl -fsSL -o /tmp/cmdline.zip \ + "https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_CMDLINE_TOOLS_VERSION}_latest.zip" \ + && unzip -q /tmp/cmdline.zip -d "${ANDROID_HOME}/cmdline-tools" \ + && mv "${ANDROID_HOME}/cmdline-tools/cmdline-tools" "${ANDROID_HOME}/cmdline-tools/latest" \ + && rm /tmp/cmdline.zip \ + && yes | sdkmanager --licenses > /dev/null \ + && sdkmanager --install "ndk;${ANDROID_NDK_VERSION}" "platform-tools" > /dev/null + +# Install gomobile at the same commit CI pins. Don't run `gomobile init` here: +# `init` resolves the NDK at runtime, do it on the first bind in the mounted +# workspace so the cache lands on the host volume. +RUN GOBIN=/usr/local/bin go install "golang.org/x/mobile/cmd/gomobile@${GOMOBILE_VERSION}" \ + && gomobile version + +WORKDIR /src + +# Default entrypoint is a plain shell so the image is composable: callers pass +# the full gomobile / gradle command they want to run. +CMD ["/bin/bash"] diff --git a/docker/build-env/windows-cross/Dockerfile b/docker/build-env/windows-cross/Dockerfile new file mode 100644 index 000000000..1288ec9c4 --- /dev/null +++ b/docker/build-env/windows-cross/Dockerfile @@ -0,0 +1,63 @@ +# Windows-cross build environment. +# +# Cross-compiles Windows .exe targets from a Linux container using +# mingw-w64. Mirrors the toolchain set used by +# .github/workflows/golang-test-windows.yml insofar as that is possible +# without a Windows kernel. +# +# IMPORTANT — what this image CAN do: +# - `GOOS=windows go build ./...` to validate that Windows builds compile +# - CGO Windows cross-compile via x86_64-w64-mingw32-gcc when CGO_ENABLED=1 +# (matches CI's choco-installed mingw-w64) +# +# IMPORTANT — what this image CANNOT do: +# - Run Windows binaries (no Windows kernel under Docker on Linux). +# - Replicate the CI's `go test` runs which execute on a real +# windows-latest runner (wintun.dll, PsExec, registry, etc.). +# Use the CI for that or a native Windows VM. +# +# Usage (from the netbird repo root): +# +# docker build -t netbird/build-windows docker/build-env/windows-cross +# +# # Cross-compile a static client (.exe) from Linux: +# docker run --rm -v "$PWD:/src" -w /src netbird/build-windows \ +# bash -c 'CGO_ENABLED=1 GOOS=windows GOARCH=amd64 \ +# CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ \ +# go build -o netbird.exe ./client' +# +# # Just validate that everything *compiles* on Windows (no CGO): +# docker run --rm -v "$PWD:/src" -w /src netbird/build-windows \ +# bash -c 'GOOS=windows GOARCH=amd64 go build ./...' +# +# Tooling versions (keep in sync with go.mod and any future explicit pin +# documented in golang-test-windows.yml): +# - Ubuntu 22.04 +# - Go 1.25.5 (matches go.mod) +# - mingw-w64 (Ubuntu package — pin further if drift becomes a problem) + +FROM ubuntu:22.04 + +ARG DEBIAN_FRONTEND=noninteractive +ARG GO_VERSION=1.25.5 + +ENV GOPATH=/go +ENV GOTOOLCHAIN=local +ENV PATH=${GOPATH}/bin:/usr/local/go/bin:${PATH} + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + git \ + build-essential \ + mingw-w64 \ + && rm -rf /var/lib/apt/lists/* + +# Install Go (matches go.mod). +RUN curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" \ + | tar -C /usr/local -xz \ + && go version + +WORKDIR /src + +CMD ["/bin/bash"]