Tutorial setup
If you have not done the prior sections, you’ll need to start the docker image:
docker run -it ghcr.io/spack/tutorial:hpcic26
and then set Spack up like this:
git clone --depth=2 --branch=releases/v1.2 https://github.com/spack/spack
. spack/share/spack/setup-env.sh
spack mirror add tutorial /mirror
spack buildcache keys --install --trust --yes-to-all
spack bootstrap now
spack compiler find
See the Basic Installation Tutorial for full details on setup.
For more help, join us in the #tutorial channel on Slack – get an invitation at slack.spack.io
Binary Caches Tutorial¶
This section covers how to share Spack-built binaries across machines and users using build caches.
Spack supports a range of storage backends for build caches: an ordinary filesystem, Amazon S3, Google Cloud Storage, and any OCI-compatible container registry (Docker Hub, GitHub Packages, a local docker registry, and so on).
We begin with the filesystem mirror that the tutorial container is already configured to use, and then move on to OCI registries, which carry the additional property that the same artifacts can be used as runnable container images.
julia is the running example throughout.
It has a non-trivial dependency in llvm and an interactive REPL that makes it easy to confirm an installation works.
Installing julia from the build cache¶
The tutorial container ships a pre-populated filesystem build cache, registered in the basics section as the signed mirror named tutorial.
Because that mirror is already active, julia and its dependencies are available as binaries without any further configuration.
Create an environment with a view and add julia to it:
$ mkdir ~/myenv && cd ~/myenv
$ spack env create --with-view view .
==> Created independent environment in: /home/spack/myenv
==> Activate with: spack env activate .
$ spack -e . add julia
==> Adding julia to environment /home/spack/myenv
Note
The terms mirror and build cache are used almost interchangeably, since every build cache is a binary mirror. Source mirrors also exist but are not covered in this tutorial.
Install the environment:
$ spack -e . install
==> Concretized 1 spec
[b] cwym5ww julia@1.12.6+openlibm+precompile build_system=makefile cpu_target=auto platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[b] 7kv4kdp ^binutils@2.46.1~debuginfod~gas~gprofng~headers~interwork~ld~libiberty~lto~nls~pgo+plugins build_system=autotools compress_debug_sections=zlib libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] ao2onuz ^diffutils@3.12 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] vbwvgwx ^libiconv@1.18 build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] yvl6jpi ^pkgconf@2.5.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] 63aruxk ^zstd@1.5.7+programs build_system=makefile compression:=none libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] mmywg7x ^compiler-wrapper@1.1.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[b] lye3uga ^curl@8.20.0~gssapi~ldap~libidn2~librtmp~libssh+libssh2+nghttp2 build_system=autotools libs:=shared,static tls:=openssl platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] j6vekwc ^dsfmt@2.2.5 build_system=makefile patches:=b79624c platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[e] yjlog5x ^gcc@15.2.0+binutils+bootstrap~graphite+libsanitizer~mold~nvptx~piclibs~profiled~strip build_system=autotools build_type=RelWithDebInfo languages:='c,c++,fortran' platform=linux os=ubuntu26.04 target=x86_64_v3
[+] xm76mt3 ^gcc-runtime@15.2.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[e] yc4n2pp ^glibc@2.43 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[+] r4lhaok ^gmake@4.4.1~guile build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] xpmsy5x ^gmp@6.3.0+cxx build_system=autotools libs:=shared,static patches:=28a6673 platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] jo3eg4r ^autoconf@2.72 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[+] yhkgfai ^automake@1.18.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] 3gdq456 ^libtool@2.5.4 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] mguwetc ^file@5.46+static build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] punbqrx ^findutils@4.10.0 build_system=autotools patches:=440b954 platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] y6uqrto ^m4@1.4.21+sigsegv build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] phcmfqk ^libsigsegv@2.15 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] xy77gc4 ^libblastrampoline@5.15.0 build_system=makefile platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] kpqpfzd ^libgit2@1.9.1~curl~ipo+mmap+ssh build_system=cmake build_type=Release generator=make https=system platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] 2pcapfx ^cmake@3.31.11~doc+ncurses+ownlibs~qtgui build_system=generic build_type=Release platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] ruqu6gz ^pcre@8.45~jit+multibyte+pic+shared+static+utf build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] ub2blr6 ^libssh2@1.11.1+shared build_system=autotools crypto=openssl platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] hhjyyqy ^xz@5.8.3~pic build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] fimmpu2 ^libunwind@1.8.3~block_signals~conservative_checks~cxx_exceptions~debug~debug_frame+docs~pic+tests+weak_backtrace~xz~zlib build_system=autotools components:=none libs:=shared,static patches:=4562c23 platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] xpk7th3 ^libuv-julia@1.48.1rc1 build_system=autotools commit=af4172ec713ee986ba1a989b9e33993a07c60c9e platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] erzdalk ^libwhich@1.3.0 build_system=makefile platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] hnjjqjh ^llvm@18.1.8~clang~cuda~flang~gold~ipo~libomptarget~libomptarget_debug+link_llvm_dylib+lld~lldb+llvm_dylib~lua~mlir~polly~python~split_dwarf~utils~z3~zstd build_system=cmake build_type=Release compiler-rt=none generator=ninja libcxx=none libunwind=none openmp=project patches:=3fdf56a,49b1a46,8459dc3,8b07b12,900363d shlib_symbol_version=JL_LLVM_18.0 targets:=amdgpu,bpf,nvptx,webassembly,x86 version_suffix=jl platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] ujctyey ^hwloc@2.13.0~cairo~cuda~gl~level_zero~libudev+libxml2~nvml~opencl+pci~rocm build_system=autotools libs:=shared,static patches:=b4db98b platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] qzkk5ym ^libpciaccess@0.17 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] o5fy6wf ^util-macros@1.20.2 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[+] ujlg2ua ^libxml2@2.15.3+pic~python+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] vh2tvd2 ^ninja@1.13.2+re2c build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] r3iq2an ^re2c@4.4 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] ew4om4t ^perl-data-dumper@2.173 build_system=perl platform=linux os=ubuntu26.04 target=x86_64_v3
[+] melg7ga ^mpfr@4.2.2 build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] sf5iutv ^autoconf-archive@2024.10.16 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[b] jvlaabk ^texinfo@7.2~xs build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] 7whskvy ^nghttp2@1.64.0 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] lkjmi5o ^openblas@0.3.33~bignuma~consistent_fpcsr+dynamic_dispatch+fortran+ilp64+locking+pic+shared~static build_system=makefile max_num_threads=512 patches:=723ddc1 symbol_suffix=64_ threads=openmp platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[b] iebfc2k ^openlibm@0.8.7 build_system=makefile platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] wvrtpeg ^openssl@3.5.5~docs+shared build_system=generic certs=mozilla platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] axeuqg3 ^ca-certificates-mozilla@2026-03-19 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[b] qnmjd2p ^p7zip@17.06 build_system=makefile platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] b3wvnvm ^patchelf@0.17.2 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] hxboy22 ^pcre2@10.44~jit+multibyte+pic build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] bvphs3b ^perl@5.42.0+cpanm+opcode+open+shared+threads build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] 27d4iyp ^berkeley-db@18.1.40+cxx~docs+stl build_system=autotools patches:=26090f4,b231fcc platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] cbtgjrh ^bzip2@1.0.8~debug~pic+shared build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] cq4dkuc ^gdbm@1.26 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] ohmdb2l ^less@692 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] kzsepw7 ^python@3.14.5+bz2+ctypes+dbm~debug~freethreading+libxml2+lzma~optimizations+pic+pyexpat+pythoncmd+readline+shared+sqlite3+ssl~static~tests~tkinter+uuid+zlib+zstd build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] d462mhw ^expat@2.8.1+libbsd build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] 7o3mv6c ^libbsd@0.12.2 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] yvvn7mu ^libmd@1.1.0 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] sle3ix4 ^gettext@1.0+bzip2+curses+git~libunistring+libxml2+pic+shared+tar+xz build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] f5xe4px ^tar@1.35 build_system=autotools zip=pigz platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] afklka7 ^pigz@2.8 build_system=makefile platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] aiceosz ^libffi@3.5.2 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] ekvivpv ^ncurses@6.6~symlinks+termlib abi=none build_system=autotools patches:=7a351bc platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] k25xiih ^readline@8.3 build_system=autotools patches:=21f0a03,72dee13,e273643 platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] unjd5da ^sqlite@3.53.1+column_metadata+fts+rtree build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] clufswx ^util-linux-uuid@2.41 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] xiro4iz ^suite-sparse@7.8.3~cuda~graphblas~openmp+pic build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[b] da5cneu ^metis@5.1.0~gdb~int64~ipo~no_warning~real64+shared build_system=cmake build_type=Release generator=make patches:=4991da9,93a7903,b1225da platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b] mujkry5 ^utf8proc@2.10.0~ipo~shared build_system=cmake build_type=Release generator=make platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] 2bqrstk ^which@2.23 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] g72d7i3 ^zlib-ng@2.3.3+compat+new_strategies+opt+pic+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[ ] mujkry5 utf8proc@2.10.0 fetching from build cache (0s)
[ ] da5cneu metis@5.1.0 fetching from build cache (0s)
[ ] qnmjd2p p7zip@17.06 fetching from build cache (0s)
[ ] wvrtpeg openssl@3.5.5 fetching from build cache (0s)
[ ] mujkry5 utf8proc@2.10.0 relocating (0s)
[ ] da5cneu metis@5.1.0 relocating (0s)
[ ] qnmjd2p p7zip@17.06 relocating (0s)
[ ] wvrtpeg openssl@3.5.5 relocating (0s)
[+] mujkry5 utf8proc@2.10.0 /home/spack/spack/opt/spack/linux-x86_64_v3/utf8proc-2.10.0-mujkry5ur3afukzumnbmy7e4hilb5i5n (0s)
[+] da5cneu metis@5.1.0 /home/spack/spack/opt/spack/linux-x86_64_v3/metis-5.1.0-da5cneuqtms6uthdt6a7hzbduvzx6672 (0s)
[ ] iebfc2k openlibm@0.8.7 fetching from build cache (0s)
[ ] lkjmi5o openblas@0.3.33 fetching from build cache (0s)
[+] qnmjd2p p7zip@17.06 /home/spack/spack/opt/spack/linux-x86_64_v3/p7zip-17.06-qnmjd2puutw7bxy33boxms3yvgsr3fb2 (1s)
[ ] 7whskvy nghttp2@1.64.0 fetching from build cache (0s)
[+] wvrtpeg openssl@3.5.5 /home/spack/spack/opt/spack/linux-x86_64_v3/openssl-3.5.5-wvrtpegflbg2z3e3obmyijvsz5lrbwy7 (1s)
[ ] iebfc2k openlibm@0.8.7 relocating (1s)
[ ] hnjjqjh llvm@18.1.8 fetching from build cache (0s)
[ ] lkjmi5o openblas@0.3.33 relocating (1s)
[+] iebfc2k openlibm@0.8.7 /home/spack/spack/opt/spack/linux-x86_64_v3/openlibm-0.8.7-iebfc2ktmby7ukpcxvhzjn77kukqkxzv (1s)
[ ] 7whskvy nghttp2@1.64.0 relocating (0s)
[ ] xpk7th3 libuv-julia@1.48.1rc1 fetching from build cache (0s)
[+] 7whskvy nghttp2@1.64.0 /home/spack/spack/opt/spack/linux-x86_64_v3/nghttp2-1.64.0-7whskvybeoszzzc3loamck65rkmxf4to (0s)
[ ] fimmpu2 libunwind@1.8.3 fetching from build cache (0s)
[ ] xpk7th3 libuv-julia@1.48.1rc1 relocating (0s)
[ ] hnjjqjh llvm@18.1.8 relocating (0s)
[+] xpk7th3 libuv-julia@1.48.1rc1 /home/spack/spack/opt/spack/linux-x86_64_v3/libuv-julia-1.48.1rc1-xpk7th3rhbls4h4jz537mfiblpar3oal (0s)
[+] lkjmi5o openblas@0.3.33 /home/spack/spack/opt/spack/linux-x86_64_v3/openblas-0.3.33-lkjmi5obqxtzb4urjbnbvo3jwk6wle4s (1s)
[ ] ruqu6gz pcre@8.45 fetching from build cache (0s)
[ ] xy77gc4 libblastrampoline@5.15.0 fetching from build cache (0s)
[ ] fimmpu2 libunwind@1.8.3 relocating (0s)
[ ] ruqu6gz pcre@8.45 relocating (1s)
[ ] xy77gc4 libblastrampoline@5.15.0 relocating (1s)
[+] fimmpu2 libunwind@1.8.3 /home/spack/spack/opt/spack/linux-x86_64_v3/libunwind-1.8.3-fimmpu2hgdfoimc7xuwtq7zy7wfygggt (1s)
[ ] j6vekwc dsfmt@2.2.5 fetching from build cache (0s)
[+] ruqu6gz pcre@8.45 /home/spack/spack/opt/spack/linux-x86_64_v3/pcre-8.45-ruqu6gzi4z2vdlwg5vwydojqilgymc6i (1s)
[+] xy77gc4 libblastrampoline@5.15.0 /home/spack/spack/opt/spack/linux-x86_64_v3/libblastrampoline-5.15.0-xy77gc4pablhhfiymlk36bjmkppltn2z (1s)
[ ] ub2blr6 libssh2@1.11.1 fetching from build cache (0s)
[ ] xiro4iz suite-sparse@7.8.3 fetching from build cache (0s)
[ ] j6vekwc dsfmt@2.2.5 relocating (0s)
[+] j6vekwc dsfmt@2.2.5 /home/spack/spack/opt/spack/linux-x86_64_v3/dsfmt-2.2.5-j6vekwcsfysu45c2lle7vxnkytbsu6am (0s)
[ ] ub2blr6 libssh2@1.11.1 relocating (0s)
[ ] xiro4iz suite-sparse@7.8.3 relocating (0s)
[+] ub2blr6 libssh2@1.11.1 /home/spack/spack/opt/spack/linux-x86_64_v3/libssh2-1.11.1-ub2blr67mf5hf7sagudpzplbkft47oqi (1s)
[+] xiro4iz suite-sparse@7.8.3 /home/spack/spack/opt/spack/linux-x86_64_v3/suite-sparse-7.8.3-xiro4iznwlfqb4ljvs4kscpuxgyfx7yg (1s)
[ ] lye3uga curl@8.20.0 fetching from build cache (0s)
[ ] kpqpfzd libgit2@1.9.1 fetching from build cache (0s)
[ ] lye3uga curl@8.20.0 relocating (0s)
[ ] kpqpfzd libgit2@1.9.1 relocating (0s)
[+] lye3uga curl@8.20.0 /home/spack/spack/opt/spack/linux-x86_64_v3/curl-8.20.0-lye3ugahqoory7dkwaj66lju7kuyipbk (0s)
[+] kpqpfzd libgit2@1.9.1 /home/spack/spack/opt/spack/linux-x86_64_v3/libgit2-1.9.1-kpqpfzdjfu4cqozj5cpwey77utq6hbrd (0s)
[+] hnjjqjh llvm@18.1.8 /home/spack/spack/opt/spack/linux-x86_64_v3/llvm-18.1.8-hnjjqjhspgojwsgvilaxhlncxed5fdtn (4s)
[ ] cwym5ww julia@1.12.6 fetching from build cache (0s)
[ ] cwym5ww julia@1.12.6 relocating (1s)
[+] cwym5ww julia@1.12.6 /home/spack/spack/opt/spack/linux-x86_64_v3/julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu (5s)
==> Updating view at /home/spack/myenv/view
Both julia and every transitive dependency, including llvm, are fetched and relocated from the tutorial mirror; nothing is built from source.
Given a build cache, the concretizer prefers concrete specs for which binaries already exist.
Confirm that the executable works through the environment’s view:
$ ./view/bin/julia -e 'println(1 + 1)'
2
Note
Build caches can be used across different Linux distributions.
The concretizer reuses specs that have a host-compatible libc (e.g. glibc or musl), and binaries built with gcc carry their compiler runtime libraries as a separate dependency, so users do not need to install a compiler first.
Setting up a local OCI build cache¶
The previous section consumed binaries from a build cache. This section covers publishing binaries to one, using an OCI container registry as the backend.
OCI registries are useful in this role because the same artifacts can serve both as a Spack build cache and as runnable container images. OCI registries in common use include Docker Hub, GitHub Container Registry (GHCR), and Amazon ECR. For this tutorial we run a registry locally, which avoids authentication:
$ docker run -d --rm -p 5000:5000 --name registry registry
Unable to find image 'registry:latest' locally
latest: Pulling from library/registry
e6f31ffc071e: Pulling fs layer
47465c9fe4b1: Pulling fs layer
269b60c1a347: Pulling fs layer
f90c3e905677: Pulling fs layer
8f4e1177a675: Pulling fs layer
f90c3e905677: Waiting
8f4e1177a675: Waiting
47465c9fe4b1: Download complete
e6f31ffc071e: Verifying Checksum
e6f31ffc071e: Download complete
269b60c1a347: Verifying Checksum
269b60c1a347: Download complete
e6f31ffc071e: Pull complete
f90c3e905677: Verifying Checksum
f90c3e905677: Download complete
8f4e1177a675: Verifying Checksum
8f4e1177a675: Download complete
47465c9fe4b1: Pull complete
269b60c1a347: Pull complete
f90c3e905677: Pull complete
8f4e1177a675: Pull complete
Digest: sha256:1be55279f18a2fe1a74edf2664cac61c1bea305b7b4642dab412e7affdcb3e33
Status: Downloaded newer image for registry:latest
6de28741a083c587ef4ebe3616332480f7d67a33960b6a88145fcee851f9a5e8
This is the official registry image from Docker Hub.
It serves an empty OCI registry on http://localhost:5000.
Add it as a second mirror:
$ spack -e . mirror add --unsigned my-registry oci+http://localhost:5000/buildcache
The URL has three parts:
oci+http://: an OCI registry over plain HTTP, without TLS. A remote registry would normally useoci://(HTTPS).localhost:5000: the registry’s host and port./buildcache: the image name under which Spack publishes all artifacts.
The environment’s spack.yaml now contains the mirror:
mirrors:
my-registry:
url: oci+http://localhost:5000/buildcache
signed: false
The same configuration works against a hosted registry such as GHCR or Docker Hub by switching to an oci:// URL and supplying credentials with --oci-username and --oci-password-variable.
Pushing to the OCI build cache¶
Push the environment to the local registry:
$ spack -e . buildcache push --without-build-dependencies my-registry
==> Selected 29 specs to push to oci+http://localhost:5000/buildcache
==> Checking for existing specs in the buildcache
==> [ 1/29] Pushed libiconv@1.18/vbwvgwx: sha256:dcc7cd303c5faa30bdb079fe70e6a426a3a72e072d5f5c04187daf99aec5b1ca (0.04s, 56.49 MB/s)
==> [ 2/29] Pushed ncurses@6.6/ekvivpv: sha256:19130f64570e8edc6f97feda9871178881c3d98dfc0fada58f4b88d5e549c580 (0.06s, 122.96 MB/s)
==> [ 3/29] Pushed libxml2@2.15.3/ujlg2ua: sha256:6b04ad61a34307d551edb2d8a668d0558a0312dd0d55abe5c1b175688002eefa (0.02s, 98.64 MB/s)
==> [ 4/29] Pushed libpciaccess@0.17/qzkk5ym: sha256:8758bd53dee435cf4ac1bfdd2ab038f850f28b3b371e51c059db3e8184c5a555 (0.02s, 11.88 MB/s)
==> [ 5/29] Pushed metis@5.1.0/da5cneu: sha256:8eefa2c562fe328775e7de46c6c63992f13b2216f22a47bca97dfc1b779c8c17 (0.02s, 24.74 MB/s)
==> [ 6/29] Pushed hwloc@2.13.0/ujctyey: sha256:fec3b5738e05882070791e2455a065314e60ddcec5de7e8ed56f883b061a72d8 (0.06s, 86.08 MB/s)
==> [ 7/29] Pushed xz@5.8.3/hhjyyqy: sha256:30b1eec3f58496db7b0c49b4ba9173979eb2731f7cb4c64841c17af09fca56c5 (0.03s, 60.02 MB/s)
==> [ 8/29] Pushed pcre@8.45/ruqu6gz: sha256:634247ca54b9bf20c87c2a4bbed2ecbc599596e11d1649eba73435f3a2f93a0b (0.03s, 99.38 MB/s)
==> [ 9/29] Pushed zlib-ng@2.3.3/g72d7i3: sha256:e546b4461b491d10dd6894a2cd608338d48ee1b14eada50af112e0654fb8fa47 (0.02s, 15.28 MB/s)
==> [10/29] Pushed utf8proc@2.10.0/mujkry5: sha256:214f2eeaaedfc39197c92c4a34117647d83e92152c16c5182d467c81ae21d3d7 (0.01s, 9.32 MB/s)
==> [11/29] Pushed suite-sparse@7.8.3/xiro4iz: sha256:45fcb3848f3feeb5b30ade878a5fdaae78336101927a7c0b7f75ade5c24b8819 (0.05s, 93.41 MB/s)
==> [12/29] Pushed pcre2@10.44/hxboy22: sha256:46032b1a40b16197220d5ca3e956a1485ee3feb3915cf5882e1630e36fb1a83b (0.02s, 75.35 MB/s)
==> [13/29] Pushed p7zip@17.06/qnmjd2p: sha256:25054009b9743530eb9d75d9efb0436cf20c53babf852765a8e9a23c3762593f (0.06s, 83.92 MB/s)
==> [14/29] Pushed openssl@3.5.5/wvrtpeg: sha256:7a37a6e2b2d29d186f2674a7fe603ee1c44f3c65d72d9a7b230e88df2e91724e (0.09s, 86.84 MB/s)
==> [15/29] Pushed openlibm@0.8.7/iebfc2k: sha256:d1a0ffc081652e375991d44ce742cc5330d3f26c18b5a691c4c66dc39c1a1ddf (0.01s, 21.17 MB/s)
==> [16/29] Pushed openblas@0.3.33/lkjmi5o: sha256:6337a03e6e93edff4bdcdd449e0764c2235e379654aecb0ded2654862e5e9d67 (0.13s, 176.04 MB/s)
==> [17/29] Pushed nghttp2@1.64.0/7whskvy: sha256:bed6bafa5dc2cbb447b84c6811a07223113a605f237e9272e893357878122212 (0.02s, 53.03 MB/s)
==> [18/29] Pushed mpfr@4.2.2/melg7ga: sha256:bdd3362c5809c565e63c3f2cbef0afa6757bdec445518701178eb2960e9309e1 (0.03s, 98.65 MB/s)
==> [19/29] Pushed llvm@18.1.8/hnjjqjh: sha256:7592dac9dccaabe8d9ecb71f4593ebce0004fae3ee1fbcd0fed2b55df2ab5e24 (0.80s, 251.66 MB/s)
==> [20/29] Pushed libuv-julia@1.48.1rc1/xpk7th3: sha256:c5f78da11cdbc9faa2c16ae7f2a7d434486ed9ee9496a3ba3aa3d7ae1ce23ef7 (0.02s, 35.88 MB/s)
==> [21/29] Pushed libunwind@1.8.3/fimmpu2: sha256:964f64d88d50830622a4806de2e27840b807f72556f2e1692ca4fb0657814351 (0.03s, 62.82 MB/s)
==> [22/29] Pushed libssh2@1.11.1/ub2blr6: sha256:99937d98ff5e7cd8267cd8b708efc479ffbbd47efbb96f61c690b6513c93b949 (0.03s, 52.03 MB/s)
==> [23/29] Pushed libgit2@1.9.1/kpqpfzd: sha256:46532207b9e2168714e67328dff2ffd23d4790e2b8a5d4863b8ade8bb12f10bd (0.08s, 23.38 MB/s)
==> [24/29] Pushed libblastrampoline@5.15.0/xy77gc4: sha256:78df85180220ebda16406cb2211e584d94d626ddbd841d388b367590258b4a7a (0.02s, 60.07 MB/s)
==> [25/29] Pushed gmp@6.3.0/xpmsy5x: sha256:96cf8ca48a1515477cbee99ebdeb221030aaa1fcc4e18559067f78a513fdcadd (0.02s, 44.69 MB/s)
==> [26/29] Pushed gcc-runtime@15.2.0/xm76mt3: sha256:ca677dae43593c3158f900ce83e932a2c95863c4bbe9aa99ddf751a258c0cd7e (0.08s, 187.75 MB/s)
==> [27/29] Pushed dsfmt@2.2.5/j6vekwc: sha256:746f91ffc3c030ccccf06d4e893513b0b13a72c1fe123f8046450b2ea002817c (0.01s, 1.15 MB/s)
==> [28/29] Pushed curl@8.20.0/lye3uga: sha256:e04350659f3378ff0ca7beed51053a29f3bc759a0364998c8d32436cf3471278 (0.03s, 46.47 MB/s)
==> [29/29] Pushed julia@1.12.6/cwym5ww: sha256:57c8e3d1e3c05364d2f62c980f1ff0ce137728e02d3df5c872d4cf9edf7a01c9 (0.72s, 208.59 MB/s)
==> Uploading manifests
==> [ 1/29] Tagged libiconv@1.18/vbwvgwx as localhost:5000/buildcache:libiconv-1.18-vbwvgwxvjrccmptlen3ebo555lk5wior.spack
==> [ 2/29] Tagged ncurses@6.6/ekvivpv as localhost:5000/buildcache:ncurses-6.6-ekvivpvwxpsfmbydk42j7me3ckftiheo.spack
==> [ 3/29] Tagged libxml2@2.15.3/ujlg2ua as localhost:5000/buildcache:libxml2-2.15.3-ujlg2uai6quwrnqjswhpatdam2owxnzh.spack
==> [ 4/29] Tagged libpciaccess@0.17/qzkk5ym as localhost:5000/buildcache:libpciaccess-0.17-qzkk5ymbu3z37kjhgylrkdy7w3hixzna.spack
==> [ 5/29] Tagged metis@5.1.0/da5cneu as localhost:5000/buildcache:metis-5.1.0-da5cneuqtms6uthdt6a7hzbduvzx6672.spack
==> [ 6/29] Tagged hwloc@2.13.0/ujctyey as localhost:5000/buildcache:hwloc-2.13.0-ujctyeyjzvata7o7oje5nefjmgqabosi.spack
==> [ 7/29] Tagged xz@5.8.3/hhjyyqy as localhost:5000/buildcache:xz-5.8.3-hhjyyqygxtpzvdyoddyypk5sfyqdcmqe.spack
==> [ 8/29] Tagged pcre@8.45/ruqu6gz as localhost:5000/buildcache:pcre-8.45-ruqu6gzi4z2vdlwg5vwydojqilgymc6i.spack
==> [ 9/29] Tagged zlib-ng@2.3.3/g72d7i3 as localhost:5000/buildcache:zlib-ng-2.3.3-g72d7i3bvgfmroytbp2d6giv67ymputp.spack
==> [10/29] Tagged utf8proc@2.10.0/mujkry5 as localhost:5000/buildcache:utf8proc-2.10.0-mujkry5ur3afukzumnbmy7e4hilb5i5n.spack
==> [11/29] Tagged suite-sparse@7.8.3/xiro4iz as localhost:5000/buildcache:suite-sparse-7.8.3-xiro4iznwlfqb4ljvs4kscpuxgyfx7yg.spack
==> [12/29] Tagged pcre2@10.44/hxboy22 as localhost:5000/buildcache:pcre2-10.44-hxboy227gopoyeoumjdkshzt5mwafkgg.spack
==> [13/29] Tagged p7zip@17.06/qnmjd2p as localhost:5000/buildcache:p7zip-17.06-qnmjd2puutw7bxy33boxms3yvgsr3fb2.spack
==> [14/29] Tagged openssl@3.5.5/wvrtpeg as localhost:5000/buildcache:openssl-3.5.5-wvrtpegflbg2z3e3obmyijvsz5lrbwy7.spack
==> [15/29] Tagged openlibm@0.8.7/iebfc2k as localhost:5000/buildcache:openlibm-0.8.7-iebfc2ktmby7ukpcxvhzjn77kukqkxzv.spack
==> [16/29] Tagged openblas@0.3.33/lkjmi5o as localhost:5000/buildcache:openblas-0.3.33-lkjmi5obqxtzb4urjbnbvo3jwk6wle4s.spack
==> [17/29] Tagged nghttp2@1.64.0/7whskvy as localhost:5000/buildcache:nghttp2-1.64.0-7whskvybeoszzzc3loamck65rkmxf4to.spack
==> [18/29] Tagged mpfr@4.2.2/melg7ga as localhost:5000/buildcache:mpfr-4.2.2-melg7gafkownovvlndh46ljc4nuf5puy.spack
==> [19/29] Tagged llvm@18.1.8/hnjjqjh as localhost:5000/buildcache:llvm-18.1.8-hnjjqjhspgojwsgvilaxhlncxed5fdtn.spack
==> [20/29] Tagged libuv-julia@1.48.1rc1/xpk7th3 as localhost:5000/buildcache:libuv-julia-1.48.1rc1-xpk7th3rhbls4h4jz537mfiblpar3oal.spack
==> [21/29] Tagged libunwind@1.8.3/fimmpu2 as localhost:5000/buildcache:libunwind-1.8.3-fimmpu2hgdfoimc7xuwtq7zy7wfygggt.spack
==> [22/29] Tagged libssh2@1.11.1/ub2blr6 as localhost:5000/buildcache:libssh2-1.11.1-ub2blr67mf5hf7sagudpzplbkft47oqi.spack
==> [23/29] Tagged libgit2@1.9.1/kpqpfzd as localhost:5000/buildcache:libgit2-1.9.1-kpqpfzdjfu4cqozj5cpwey77utq6hbrd.spack
==> [24/29] Tagged libblastrampoline@5.15.0/xy77gc4 as localhost:5000/buildcache:libblastrampoline-5.15.0-xy77gc4pablhhfiymlk36bjmkppltn2z.spack
==> [25/29] Tagged gmp@6.3.0/xpmsy5x as localhost:5000/buildcache:gmp-6.3.0-xpmsy5xffenfvl6lc5shb5a5krckrznd.spack
==> [26/29] Tagged gcc-runtime@15.2.0/xm76mt3 as localhost:5000/buildcache:gcc-runtime-15.2.0-xm76mt35elmqwrjdlibzhngqkiqnyq4p.spack
==> [27/29] Tagged dsfmt@2.2.5/j6vekwc as localhost:5000/buildcache:dsfmt-2.2.5-j6vekwcsfysu45c2lle7vxnkytbsu6am.spack
==> [28/29] Tagged curl@8.20.0/lye3uga as localhost:5000/buildcache:curl-8.20.0-lye3ugahqoory7dkwaj66lju7kuyipbk.spack
==> [29/29] Tagged julia@1.12.6/cwym5ww as localhost:5000/buildcache:julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu.spack
Two things about this invocation are worth noting.
The --without-build-dependencies flag is passed because julia was installed from a binary cache, so build-only dependencies like cmake are not present on this machine.
Without the flag, Spack would report that those packages are not installed.
All artifacts live under the single image name localhost:5000/buildcache.
Spack auto-generates one tag per spec, of the form <name>-<version>-<hash>.spack, including the package hash so that each spec resolves to a distinct tag.
Re-running the push detects that nothing needs to be uploaded:
$ spack -e . buildcache push --without-build-dependencies my-registry
==> Selected 29 specs to push to oci+http://localhost:5000/buildcache
==> Checking for existing specs in the buildcache
==> All specs are already in the buildcache. Use --force to overwrite them.
Reinstalling from the OCI build cache¶
So far julia could have come from either mirror.
To confirm that the OCI registry works as a build cache on its own, disable the filesystem tutorial mirror by changing mirrors: to mirrors:: in spack.yaml.
The trailing :: replaces, rather than extends, the mirrors inherited from Spack’s global configuration:
mirrors::
my-registry:
url: oci+http://localhost:5000/buildcache
signed: false
Reinstall julia with --overwrite.
Only julia is reinstalled; its dependencies remain installed and are not refetched.
$ spack -e . install --overwrite -y julia
[ ] cwym5ww julia@1.12.6 fetching from build cache (0s)
[ ] cwym5ww julia@1.12.6 relocating (0s)
[+] cwym5ww julia@1.12.6 /home/spack/spack/opt/spack/linux-x86_64_v3/julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu (4s)
Each spec is stored as two blobs: a JSON manifest and the binary tarball.
OCI registries are content-addressed, hence the sha256:... identifiers shown in the push output rather than human-readable filenames.
Creating runnable container images¶
So far the OCI registry has been used only as a Spack build cache.
Since the artifacts are also valid OCI images, they can be pulled directly with docker.
Consider what happens when running an image without a base image:
$ docker run --rm localhost:5000/buildcache:julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu.spack julia -e 'println(1 + 1)'
Unable to find image 'localhost:5000/buildcache:julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu.spack' locally
julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu.spack: Pulling from buildcache
1B677dae4359: Pulling fs layer
1B46b4461b49: Pulling fs layer
1Bb1eec3f584: Pulling fs layer
1Bc7cd303c5f: Pulling fs layer
1Bcf8ca48a15: Pulling fs layer
1B130f64570e: Pulling fs layer
1B04ad61a343: Pulling fs layer
1B58bd53dee4: Pulling fs layer
1B37a6e2b2d2: Pulling fs layer
1B37a03e6e93: Pulling fs layer
1Bd3362c5809: Pulling fs layer
1Befa2c562fe: Pulling fs layer
1Bc3b5738e05: Pulling fs layer
1B4247ca54b9: Pulling fs layer
1B937d98ff5e: Pulling fs layer
1Bd6bafa5dc2: Pulling fs layer
1B4f2eeaaedf: Pulling fs layer
1Bfcb3848f3f: Pulling fs layer
1B032b1a40b1: Pulling fs layer
1B054009b974: Pulling fs layer
1Ba0ffc08165: Pulling fs layer
1B92dac9dcca: Pulling fs layer
1Bf78da11cdb: Pulling fs layer
1B4f64d88d50: Pulling fs layer
1B532207b9e2: Pulling fs layer
1Bdf85180220: Pulling fs layer
1B6f91ffc3c0: Pulling fs layer
1B4350659f33: Pulling fs layer
1BDigest:3sha256:1f7410e032fce4b2ac8bdbf30b797eb823c394596f73f098b0de4bbeda5ce19a58.4MB/158.4MBB
Status: Downloaded newer image for localhost:5000/buildcache:julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu.spack
exec /home/spack/spack/opt/spack/linux-x86_64_v3/julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu/bin/julia: no such file or directory
The run fails because the layers we pushed contain the Spack-built artifacts but not the host’s glibc, which Spack always treats as an external package.
Without a base image the container has no /lib directory at all, which produces the error above.
The resolution is to push again with --base-image pointing at a minimal distribution that provides a compatible glibc:
$ spack -e . buildcache push --force --without-build-dependencies --base-image ubuntu:26.04 my-registry
==> Selected 29 specs to push to oci+http://localhost:5000/buildcache
==> [ 1/29] Pushed libiconv@1.18/vbwvgwx: sha256:dcc7cd303c5faa30bdb079fe70e6a426a3a72e072d5f5c04187daf99aec5b1ca (0.03s, 73.54 MB/s)
==> [ 2/29] Pushed ncurses@6.6/ekvivpv: sha256:19130f64570e8edc6f97feda9871178881c3d98dfc0fada58f4b88d5e549c580 (0.04s, 196.20 MB/s)
==> [ 3/29] Pushed libxml2@2.15.3/ujlg2ua: sha256:6b04ad61a34307d551edb2d8a668d0558a0312dd0d55abe5c1b175688002eefa (0.03s, 72.29 MB/s)
==> [ 4/29] Pushed libpciaccess@0.17/qzkk5ym: sha256:8758bd53dee435cf4ac1bfdd2ab038f850f28b3b371e51c059db3e8184c5a555 (0.03s, 5.76 MB/s)
==> [ 5/29] Pushed metis@5.1.0/da5cneu: sha256:8eefa2c562fe328775e7de46c6c63992f13b2216f22a47bca97dfc1b779c8c17 (0.00s, 151.85 MB/s)
==> [ 6/29] Pushed hwloc@2.13.0/ujctyey: sha256:fec3b5738e05882070791e2455a065314e60ddcec5de7e8ed56f883b061a72d8 (0.00s, 2272.84 MB/s)
==> [ 7/29] Pushed xz@5.8.3/hhjyyqy: sha256:30b1eec3f58496db7b0c49b4ba9173979eb2731f7cb4c64841c17af09fca56c5 (0.00s, 779.85 MB/s)
==> [ 8/29] Pushed pcre@8.45/ruqu6gz: sha256:634247ca54b9bf20c87c2a4bbed2ecbc599596e11d1649eba73435f3a2f93a0b (0.00s, 727.80 MB/s)
==> [ 9/29] Pushed zlib-ng@2.3.3/g72d7i3: sha256:e546b4461b491d10dd6894a2cd608338d48ee1b14eada50af112e0654fb8fa47 (0.00s, 130.94 MB/s)
==> [10/29] Pushed utf8proc@2.10.0/mujkry5: sha256:214f2eeaaedfc39197c92c4a34117647d83e92152c16c5182d467c81ae21d3d7 (0.00s, 53.34 MB/s)
==> [11/29] Pushed suite-sparse@7.8.3/xiro4iz: sha256:45fcb3848f3feeb5b30ade878a5fdaae78336101927a7c0b7f75ade5c24b8819 (0.00s, 1805.60 MB/s)
==> [12/29] Pushed pcre2@10.44/hxboy22: sha256:46032b1a40b16197220d5ca3e956a1485ee3feb3915cf5882e1630e36fb1a83b (0.00s, 545.67 MB/s)
==> [13/29] Pushed p7zip@17.06/qnmjd2p: sha256:25054009b9743530eb9d75d9efb0436cf20c53babf852765a8e9a23c3762593f (0.00s, 1047.45 MB/s)
==> [14/29] Pushed openssl@3.5.5/wvrtpeg: sha256:7a37a6e2b2d29d186f2674a7fe603ee1c44f3c65d72d9a7b230e88df2e91724e (0.00s, 3895.76 MB/s)
==> [15/29] Pushed openlibm@0.8.7/iebfc2k: sha256:d1a0ffc081652e375991d44ce742cc5330d3f26c18b5a691c4c66dc39c1a1ddf (0.00s, 139.36 MB/s)
==> [16/29] Pushed openblas@0.3.33/lkjmi5o: sha256:6337a03e6e93edff4bdcdd449e0764c2235e379654aecb0ded2654862e5e9d67 (0.00s, 9442.38 MB/s)
==> [17/29] Pushed nghttp2@1.64.0/7whskvy: sha256:bed6bafa5dc2cbb447b84c6811a07223113a605f237e9272e893357878122212 (0.00s, 253.35 MB/s)
==> [18/29] Pushed mpfr@4.2.2/melg7ga: sha256:bdd3362c5809c565e63c3f2cbef0afa6757bdec445518701178eb2960e9309e1 (0.00s, 1166.02 MB/s)
==> [19/29] Pushed llvm@18.1.8/hnjjqjh: sha256:7592dac9dccaabe8d9ecb71f4593ebce0004fae3ee1fbcd0fed2b55df2ab5e24 (0.00s, 102162.34 MB/s)
==> [20/29] Pushed libuv-julia@1.48.1rc1/xpk7th3: sha256:c5f78da11cdbc9faa2c16ae7f2a7d434486ed9ee9496a3ba3aa3d7ae1ce23ef7 (0.00s, 271.41 MB/s)
==> [21/29] Pushed libunwind@1.8.3/fimmpu2: sha256:964f64d88d50830622a4806de2e27840b807f72556f2e1692ca4fb0657814351 (0.00s, 816.33 MB/s)
==> [22/29] Pushed libssh2@1.11.1/ub2blr6: sha256:99937d98ff5e7cd8267cd8b708efc479ffbbd47efbb96f61c690b6513c93b949 (0.00s, 586.24 MB/s)
==> [23/29] Pushed libgit2@1.9.1/kpqpfzd: sha256:46532207b9e2168714e67328dff2ffd23d4790e2b8a5d4863b8ade8bb12f10bd (0.00s, 712.30 MB/s)
==> [24/29] Pushed libblastrampoline@5.15.0/xy77gc4: sha256:78df85180220ebda16406cb2211e584d94d626ddbd841d388b367590258b4a7a (0.00s, 507.95 MB/s)
==> [25/29] Pushed gmp@6.3.0/xpmsy5x: sha256:96cf8ca48a1515477cbee99ebdeb221030aaa1fcc4e18559067f78a513fdcadd (0.00s, 360.48 MB/s)
==> [26/29] Pushed gcc-runtime@15.2.0/xm76mt3: sha256:ca677dae43593c3158f900ce83e932a2c95863c4bbe9aa99ddf751a258c0cd7e (0.00s, 6470.49 MB/s)
==> [27/29] Pushed dsfmt@2.2.5/j6vekwc: sha256:746f91ffc3c030ccccf06d4e893513b0b13a72c1fe123f8046450b2ea002817c (0.00s, 8.66 MB/s)
==> [28/29] Pushed curl@8.20.0/lye3uga: sha256:e04350659f3378ff0ca7beed51053a29f3bc759a0364998c8d32436cf3471278 (0.00s, 571.91 MB/s)
==> [29/29] Pushed julia@1.12.6/cwym5ww: sha256:74ef2483ad158ba531945f56f8be44405ec303868ad2c553118ec4616abe794c (0.41s, 370.54 MB/s)
==> Uploading manifests
==> [ 1/29] Tagged libiconv@1.18/vbwvgwx as localhost:5000/buildcache:libiconv-1.18-vbwvgwxvjrccmptlen3ebo555lk5wior.spack
==> [ 2/29] Tagged ncurses@6.6/ekvivpv as localhost:5000/buildcache:ncurses-6.6-ekvivpvwxpsfmbydk42j7me3ckftiheo.spack
==> [ 3/29] Tagged libxml2@2.15.3/ujlg2ua as localhost:5000/buildcache:libxml2-2.15.3-ujlg2uai6quwrnqjswhpatdam2owxnzh.spack
==> [ 4/29] Tagged libpciaccess@0.17/qzkk5ym as localhost:5000/buildcache:libpciaccess-0.17-qzkk5ymbu3z37kjhgylrkdy7w3hixzna.spack
==> [ 5/29] Tagged metis@5.1.0/da5cneu as localhost:5000/buildcache:metis-5.1.0-da5cneuqtms6uthdt6a7hzbduvzx6672.spack
==> [ 6/29] Tagged hwloc@2.13.0/ujctyey as localhost:5000/buildcache:hwloc-2.13.0-ujctyeyjzvata7o7oje5nefjmgqabosi.spack
==> [ 7/29] Tagged xz@5.8.3/hhjyyqy as localhost:5000/buildcache:xz-5.8.3-hhjyyqygxtpzvdyoddyypk5sfyqdcmqe.spack
==> [ 8/29] Tagged pcre@8.45/ruqu6gz as localhost:5000/buildcache:pcre-8.45-ruqu6gzi4z2vdlwg5vwydojqilgymc6i.spack
==> [ 9/29] Tagged zlib-ng@2.3.3/g72d7i3 as localhost:5000/buildcache:zlib-ng-2.3.3-g72d7i3bvgfmroytbp2d6giv67ymputp.spack
==> [10/29] Tagged utf8proc@2.10.0/mujkry5 as localhost:5000/buildcache:utf8proc-2.10.0-mujkry5ur3afukzumnbmy7e4hilb5i5n.spack
==> [11/29] Tagged suite-sparse@7.8.3/xiro4iz as localhost:5000/buildcache:suite-sparse-7.8.3-xiro4iznwlfqb4ljvs4kscpuxgyfx7yg.spack
==> [12/29] Tagged pcre2@10.44/hxboy22 as localhost:5000/buildcache:pcre2-10.44-hxboy227gopoyeoumjdkshzt5mwafkgg.spack
==> [13/29] Tagged p7zip@17.06/qnmjd2p as localhost:5000/buildcache:p7zip-17.06-qnmjd2puutw7bxy33boxms3yvgsr3fb2.spack
==> [14/29] Tagged openssl@3.5.5/wvrtpeg as localhost:5000/buildcache:openssl-3.5.5-wvrtpegflbg2z3e3obmyijvsz5lrbwy7.spack
==> [15/29] Tagged openlibm@0.8.7/iebfc2k as localhost:5000/buildcache:openlibm-0.8.7-iebfc2ktmby7ukpcxvhzjn77kukqkxzv.spack
==> [16/29] Tagged openblas@0.3.33/lkjmi5o as localhost:5000/buildcache:openblas-0.3.33-lkjmi5obqxtzb4urjbnbvo3jwk6wle4s.spack
==> [17/29] Tagged nghttp2@1.64.0/7whskvy as localhost:5000/buildcache:nghttp2-1.64.0-7whskvybeoszzzc3loamck65rkmxf4to.spack
==> [18/29] Tagged mpfr@4.2.2/melg7ga as localhost:5000/buildcache:mpfr-4.2.2-melg7gafkownovvlndh46ljc4nuf5puy.spack
==> [19/29] Tagged llvm@18.1.8/hnjjqjh as localhost:5000/buildcache:llvm-18.1.8-hnjjqjhspgojwsgvilaxhlncxed5fdtn.spack
==> [20/29] Tagged libuv-julia@1.48.1rc1/xpk7th3 as localhost:5000/buildcache:libuv-julia-1.48.1rc1-xpk7th3rhbls4h4jz537mfiblpar3oal.spack
==> [21/29] Tagged libunwind@1.8.3/fimmpu2 as localhost:5000/buildcache:libunwind-1.8.3-fimmpu2hgdfoimc7xuwtq7zy7wfygggt.spack
==> [22/29] Tagged libssh2@1.11.1/ub2blr6 as localhost:5000/buildcache:libssh2-1.11.1-ub2blr67mf5hf7sagudpzplbkft47oqi.spack
==> [23/29] Tagged libgit2@1.9.1/kpqpfzd as localhost:5000/buildcache:libgit2-1.9.1-kpqpfzdjfu4cqozj5cpwey77utq6hbrd.spack
==> [24/29] Tagged libblastrampoline@5.15.0/xy77gc4 as localhost:5000/buildcache:libblastrampoline-5.15.0-xy77gc4pablhhfiymlk36bjmkppltn2z.spack
==> [25/29] Tagged gmp@6.3.0/xpmsy5x as localhost:5000/buildcache:gmp-6.3.0-xpmsy5xffenfvl6lc5shb5a5krckrznd.spack
==> [26/29] Tagged gcc-runtime@15.2.0/xm76mt3 as localhost:5000/buildcache:gcc-runtime-15.2.0-xm76mt35elmqwrjdlibzhngqkiqnyq4p.spack
==> [27/29] Tagged dsfmt@2.2.5/j6vekwc as localhost:5000/buildcache:dsfmt-2.2.5-j6vekwcsfysu45c2lle7vxnkytbsu6am.spack
==> [28/29] Tagged curl@8.20.0/lye3uga as localhost:5000/buildcache:curl-8.20.0-lye3ugahqoory7dkwaj66lju7kuyipbk.spack
==> [29/29] Tagged julia@1.12.6/cwym5ww as localhost:5000/buildcache:julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu.spack
The base image’s libc must be at least as new as the one used at build time, otherwise the binaries fail at runtime with errors of the form version `GLIBC_2.38' not found.
The distribution itself need not match.
archlinux:latest, for example, ships a sufficiently recent glibc while providing a different userland (pacman instead of apt, and so on).
The image now runs.
Because the tag was pushed once already, docker has the old single-layer image cached locally; --pull always forces it to fetch the rebuilt image with the base layer:
$ docker run --rm --pull always localhost:5000/buildcache:julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu.spack julia -e 'println(1 + 1)'
julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu.spack: Pulling from buildcache
1B819469700f: Pulling fs layer
1B679419df18: Pulling fs layer
1B677dae4359: Pulling fs layer
1B46b4461b49: Pulling fs layer
1Bb1eec3f584: Pulling fs layer
1Bc7cd303c5f: Pulling fs layer
1Bcf8ca48a15: Pulling fs layer
1B130f64570e: Pulling fs layer
1B04ad61a343: Pulling fs layer
1B58bd53dee4: Pulling fs layer
1B37a6e2b2d2: Pulling fs layer
1B37a03e6e93: Pulling fs layer
1Bd3362c5809: Pulling fs layer
1Befa2c562fe: Pulling fs layer
1Bc3b5738e05: Pulling fs layer
1B4247ca54b9: Pulling fs layer
1B937d98ff5e: Pulling fs layer
1Bd6bafa5dc2: Pulling fs layer
1B4f2eeaaedf: Pulling fs layer
1Bfcb3848f3f: Pulling fs layer
1B032b1a40b1: Pulling fs layer
1B054009b974: Pulling fs layer
1Ba0ffc08165: Pulling fs layer
1B92dac9dcca: Pulling fs layer
1Bf78da11cdb: Pulling fs layer
1B4f64d88d50: Pulling fs layer
1B532207b9e2: Pulling fs layer
1Bdf85180220: Pulling fs layer
1B6f91ffc3c0: Pulling fs layer
1B4350659f33: Pulling fs layer
1BDigest:dsha256:5d0452d90f2ef02df959fcb3277e31d35f4df46cea7453a1d2d96c0002fc44d258.4MB/158.4MBB
Status: Downloaded newer image for localhost:5000/buildcache:julia-1.12.6-cwym5wwcr7mnaap6okxtqeljftjv3lpu.spack
2
In addition to glibc, the base image provides a shell and the standard utilities.
Spack environments as container images¶
The preceding section produced one image per package. For most uses a single image containing the full environment is more convenient.
Add a text editor to the environment, so that the image can both edit and run Julia code:
$ spack -e . install --add vim
==> Warning: the mirror at oci+http://localhost:5000/buildcache cannot be used in concretization (no index found)
==> Concretized 1 spec
[b] 2w6tqad vim@9.2.0000~cscope~gui~lua~perl~python~ruby~x build_system=autotools features=normal platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] mmywg7x ^compiler-wrapper@1.1.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[+] punbqrx ^findutils@4.10.0 build_system=autotools patches:=440b954 platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] sle3ix4 ^gettext@1.0+bzip2+curses+git~libunistring+libxml2+pic+shared+tar+xz build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] cbtgjrh ^bzip2@1.0.8~debug~pic+shared build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b] ao2onuz ^diffutils@3.12 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] vbwvgwx ^libiconv@1.18 build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] ujlg2ua ^libxml2@2.15.3+pic~python+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] g72d7i3 ^zlib-ng@2.3.3+compat+new_strategies+opt+pic+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] f5xe4px ^tar@1.35 build_system=autotools zip=pigz platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] afklka7 ^pigz@2.8 build_system=makefile platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] 63aruxk ^zstd@1.5.7+programs build_system=makefile compression:=none libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] hhjyyqy ^xz@5.8.3~pic build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[e] yjlog5x ^gcc@15.2.0+binutils+bootstrap~graphite+libsanitizer~mold~nvptx~piclibs~profiled~strip build_system=autotools build_type=RelWithDebInfo languages:='c,c++,fortran' platform=linux os=ubuntu26.04 target=x86_64_v3
[+] xm76mt3 ^gcc-runtime@15.2.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[e] yc4n2pp ^glibc@2.43 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[+] r4lhaok ^gmake@4.4.1~guile build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+] ekvivpv ^ncurses@6.6~symlinks+termlib abi=none build_system=autotools patches:=7a351bc platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+] yvl6jpi ^pkgconf@2.5.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[ ] 2w6tqad vim@9.2.0000 fetching from build cache (0s)
[ ] 2w6tqad vim@9.2.0000 relocating (0s)
[+] 2w6tqad vim@9.2.0000 /home/spack/spack/opt/spack/linux-x86_64_v3/vim-9.2.0000-2w6tqadqxniojqyzoe4j55jamd4pbbcp (1s)
==> Updating view at /home/spack/myenv/view
Note
With the tutorial mirror disabled, vim is built from source.
Change mirrors:: back to mirrors: first to install it from the tutorial cache; either way the build is quick.
Pass --tag to assign the environment image a human-readable name:
$ spack -e . buildcache push --without-build-dependencies --base-image ubuntu:26.04 --tag julia-and-vim my-registry
==> Selected 30 specs to push to oci+http://localhost:5000/buildcache
==> Checking for existing specs in the buildcache
==> 1 specs need to be pushed to localhost:5000/buildcache
==> Pushed vim@9.2.0000/2w6tqad: sha256:70cb96a70621c93e218eb507055f429d04785693c7b3811982e9a3c26a3230d8 (0.06s, 185.17 MB/s)
==> Using cached archive: /home/spack/spack/var/spack/cache/blobs/sha256/de7345b16e942e22044c6ba053020ec85ae879984860a9918517d54eb6cef851
==> Uploading manifests
==> Tagged vim@9.2.0000/2w6tqad as localhost:5000/buildcache:vim-9.2.0000-2w6tqadqxniojqyzoe4j55jamd4pbbcp.spack
==> The following 29 specs were skipped as they already exist in the buildcache:
libiconv@1.18/vbwvgwx, libxml2@2.15.3/ujlg2ua, libpciaccess@0.17/qzkk5ym, metis@5.1.0/da5cneu, ..., julia@1.12.6/cwym5ww
Use --force to overwrite them.
==> Tagged localhost:5000/buildcache:julia-and-vim
Spack publishes each package as its own image layer.
Layers are shared between image tags, so the combined image takes almost no extra storage.
Unlike Docker, where each RUN line creates a layer that depends on the previous one, Spack package layers are independent and can be combined in any order.
Run the combined image:
$ docker run -it --rm localhost:5000/buildcache:julia-and-vim
root@f53920f8695a:/# vim example.jl # write some Julia code
root@f53920f8695a:/# julia example.jl # and run it
Both julia and vim are immediately usable because Spack writes PATH into the image’s environment, pointing at each package’s install prefix.
Spack does not materialize the environment’s view inside the image; the packages live at their original Spack prefixes, identical to those on the host.
Relation to docker build workflows¶
In earlier versions of Spack the common practice was to generate a Dockerfile from a Spack environment using spack containerize and then build the image with docker build:
FROM <base image> AS build
COPY spack.yaml /root/env/spack.yaml
RUN spack -e /root/env install
FROM <base image>
COPY --from=build /opt/spack/opt /opt/spack/opt
This approach still works and spack containerize is still available, but it has several drawbacks:
If
RUN spack -e /root/env installfails, Docker discards the whole layer, including any successfully built dependencies. Troubleshooting typically requires starting from scratch in adocker runsession.Some CI environments cannot run
docker buildsafely — for example, when the CI script itself runs inside a container (“Docker-in-Docker”).
The OCI build cache approach decouples the three responsibilities that docker build combines: build isolation, running the build, and producing an image.
spack install can be run in any environment (host, sandbox, container), and spack buildcache push then turns the result into images.
Relocation¶
Spack installs packages under an arbitrary prefix, typically ~/spack/opt/spack/....
This is more flexible than most package managers, but it also means that binaries contain absolute paths to machine-specific locations, which must be rewritten when the binary is reinstalled elsewhere.
Spack does this rewriting automatically when installing from a binary cache. When producing binaries that are meant to be redistributed, one constraint applies: Spack can only relocate paths in a binary if the target prefix is no longer than the prefix used at build time.
The reason is that absolute paths typically reside in the binary’s string table — a list of null-terminated strings referenced by offset. Strings can be edited in place, but they cannot grow without overwriting their neighbors.
To maximize the likelihood of successful relocation, build in a relatively long path. Spack can pad install prefixes automatically:
$ spack -e . config add config:install_tree:padded_length:256
Using build caches in CI¶
Build caches also speed up CI pipelines. Both GitHub Actions and GitLab CI support container registries, so the workflow described above applies directly in CI.
Spack provides a GitHub Action that configures a shared build cache:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Set up Spack
uses: spack/setup-spack@v2
- run: spack install python # uses a shared build cache
See the setup-spack readme for instructions on caching additional binaries that are not in the shared build cache.
Summary¶
This tutorial covered:
installing
juliafrom the pre-configuredtutorialbuild cache without any source builds;setting up a local OCI registry as a second build cache and pushing the environment to it;
reinstalling from the OCI cache to confirm that it functions as a regular Spack mirror;
using the same OCI artifacts as runnable container images, both per-package and as a combined environment with
--tag.