Pull static binaries from wolfi
21 March, 2024 - Tags: binaries, wolfi
I have been using wolfi as a package manager for static binaries and this document explains the same process.
TLDR: I mount my bin
directory inside the container and then I add the static binaries using apk.
Why?
If you're doing something around kubernetes then there's a lot of things that you need. The tools I often use are k9s
, helm
, kubectl
etc. How do I ensure that I get latest version of these binaries on my system?
In the past, I've used arkade
and still do. This is really smooth. You don't have to goto GitHub releases page and copy the URL, come back to your terminal and use wget
or curl
to download the tarball/binary.
Now, how to do the same with wolfi.
$ docker run --name wolfi-install -v $HOME/.arkade/bin:/usr/bin --rm -it cgr.dev/chainguard/wolfi-base:latest sh -c 'apk add k9s'
fetch https://packages.wolfi.dev/os/x86_64/APKINDEX.tar.gz
(1/1) Installing k9s (0.32.3-r1)
OK: 133 MiB in 15 packages
In the command above, I have mounted my ~/.arkade/bin
which is already there in the PATH
and then I executed a command apk add k9s
inside the container.
One may say that this command is really long and I don't want that. I used a simple just
target to make the process easier for me.
# install something in ~/.arkade/bin/
wolfi-install *package: clean
docker run --name wolfi-install -v $HOME/.arkade/bin:/usr/bin --rm -it cgr.dev/chainguard/wolfi-base:latest sh -c 'apk add {{package}}'
# just install a package in current working directory (./package)
wolfi-install-here *package:
docker run --rm -it -v .:/usr/bin cgr.dev/chainguard/wolfi-base:latest sh -c 'apk add {{package}}'
I use the above two just recipes install things either in my path or current working directory.
So, if I want to update my k9s
binary then I use just wolfi-install k9s
and if I want a temporary binary in my current working directory then we can do use the command just wolfi-install-here <pkg-name>
NOTE: Just doesn't support global justfile as of now so I have a global justfile located at ~/.justfile
and I invoke the following commands in my system.
just --justfile ~/.justfile wolfi-install k9s
just --justfile ~/.justfile wolfi-install-here hcloud
This works pretty good for me.
I use the same approach while working with container as well.
On this project, we put everything inside the container and then copy the same binaries on the host system tracked by a version.txt
file.
What don't go well?
Packages that depend on shared system libraries break if you just install the binary. Think about the package that ties to a particular version of openssl and you don't have the same version on your host system then it will break. Mostly rust binaries have done some trouble for me in the past but some works (atuin, eza, ripgrep, fd) but some doesn't for example (lychee and few others)
From Go ecosystem, the binaries that are dynamically linked with CGO shouldn't be installed this way. They usually create problem for me.
If you're able to peek into the detailed output of ldd
and realelf
then you can install the binaries anyway and download the shared libraries on your system to make it work. But again, I wanted things to be simpler and fast and for that reason, I only pull static binaries from wolfi and some dynamically linked binaries as well that have worked in past for me.
Example:
By invoking the following command, you can see the dependency of the rg
binary.
$ readelf -d $(command -v rg)
Dynamic section at offset 0x5861d0 contains 29 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
Thanks to the contributors and maintainers of wolfi for maintaining zero CVE packages.
On remote systems
Sometimes just is installed on the VM on which I'm running but docker
is installed, I use the following.
docker run --rm -v .:/usr/bin/ cgr.dev/chainguard/wolfi-base:latest sh -c 'apk add lazygit'
fetch https://packages.wolfi.dev/os/x86_64/APKINDEX.tar.gz
(1/1) Installing lazygit (0.41.0-r0)
OK: 32 MiB in 15 packages
BIG WARNING: If you mount your libraries path inside the container and something weird happens then you're responsible for it. Please don't do that. That's highly risky and I'm pretty sure very dangerous as well given that'll break something your system. I think only mounting something in your home directory (~/.local/bin or ~/.arkade/bin) is the hacky (probably still unsecure) but way to do it. Don't mount any lib directories from your filesystem.