Those builds are dynamically linking to glibc, and using some symbols from new-ish versions. As a result, using them on a just-slightly-older Linux environment (e.g. Ubuntu 20.04, which has glibc 2.31), results in errors like the following:
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /opt/work/bin/canary_linux_amd64)
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /opt/work/bin/canary_linux_amd64)
This proposes setting CGO_ENABLED=0 when cross-compiling for Linux, so the artifact will statically link in what it needs and therefore be usable on systems with older glibc.
I chose to set this inline in the 2 Linux builds in make package so that if you run make package locally on a Linux system, it'll produce a similar artifact to the one produced in CI. To hopefully improve the chance of local tests catching issues.
But happy to change to any of these alternatives if someone has a compelling reason:
set it globally in the environment of the CI job(s)
set it for allgo build commands in make package (not just Linux)
set it in some other place
Won't statically linking make the binary bigger?
I didn't find any meaningful change in binary size as a result of doing this. With and without CGO_ENABLED, canary_linux_amd64 was about 21MB.
Description
This project's release artifacts are currently built in a VM using GitHub Actions'
ubuntu-latest
image.https://github.com/NVIDIA/container-canary/blob/a4f5c799e64cdaec661d40b909d04ca505b3e191/.github/workflows/upload-release-assets.yaml#L11
As of today, that's Ubuntu 22.04 (actions/runner-images), which has glibc 2.35.
Those builds are dynamically linking to glibc, and using some symbols from new-ish versions. As a result, using them on a just-slightly-older Linux environment (e.g. Ubuntu 20.04, which has glibc 2.31), results in errors like the following:
This proposes setting
CGO_ENABLED=0
when cross-compiling for Linux, so the artifact will statically link in what it needs and therefore be usable on systems with older glibc.Notes for Reviewers
How I tested this
built with this setting on and off on Ubuntu 22.04, tested on Ubuntu 20.04 (click for details)
Built inside an Ubuntu 22.04 image ```shell docker run \ --rm \ -v $(pwd):/opt/work \ -w /opt/work \ -it ubuntu:22.04 \ bash apt-get update apt-get install -y --no-install-recommends \ build-essential \ ca-certificates \ git \ golang-go git config --global --add safe.directory /opt/work # build with default settings make package mv bin bin-cgo # build with CGO off export CGO_ENABLED=0 make package mv bin bin-no-cgo ``` Tried using those on Ubuntu 20.04. The CGO-enabled one failed to run. ```shell docker run \ --rm \ -v $(pwd):/opt/work:ro \ -it ubuntu:20.04 \ /opt/work/bin-cgo/canary_linux_amd64 version # /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /opt/work/bin-cgo/canary_linux_amd64) # /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /opt/work/bin-cgo/canary_linux_amd64) ``` But the no-cgo one worked! ```shell docker run \ --rm \ -v $(pwd):/opt/work:ro \ -it ubuntu:20.04 \ /opt/work/bin-no-cgo/canary_linux_amd64 version # Container Canary # Version: a4f5c79-dirty # Go Version: go1.18.1 # Commit: a4f5c79 # OS/Arch: linux/amd64 # Built: 2024-05-24T17:12:44Z ``` And the no-cgo one worked validating an image! Ran the following outside of Docker, on an Ubuntu 20.04 VM. ```shell bin-no-cgo/canary_linux_amd64 validate \ --file https://raw.githubusercontent.com/NVIDIA/container-canary/main/examples/kubeflow.yaml \ "ghcr.io/dask/dask-notebook" ``` ```text Validating ghcr.io/dask/dask-notebook against kubeflow π User ID is 1000 [passed] π Home directory is /home/jovyan [passed] π© User is jovyan [passed] π Exposes an HTTP interface on port 8888 [passed] π Sets 'Access-Control-Allow-Origin: *' header [passed] π§ Correctly routes the NB_PREFIX [passed] validation passed ```Why not set this in the CI environment?
I chose to set this inline in the 2 Linux builds in
make package
so that if you runmake package
locally on a Linux system, it'll produce a similar artifact to the one produced in CI. To hopefully improve the chance of local tests catching issues.But happy to change to any of these alternatives if someone has a compelling reason:
go build
commands inmake package
(not just Linux)Won't statically linking make the binary bigger?
I didn't find any meaningful change in binary size as a result of doing this. With and without
CGO_ENABLED
,canary_linux_amd64
was about 21MB.References