chainguard-dev / apko

Build OCI images from APK packages directly without Dockerfile

Home Page:https://apko.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature: Offline mode

jonjohnsonjr opened this issue · comments

Background

As part of resolving the world, the first thing we do is fetch signing keys and HEAD APKINDEX.tar.gz to see if we have it in our cache (see #776).

Our cache currently (at go-apk HEAD) looks something like this:

$ tree
.
├── APKINDEX
│   ├── 1f8feef7ae437f0088ddb191b9f76f51.tar.gz
│   ├── 3e3bfe9f1038a798fa2d4ccc8f1be0de.tar.gz
│   ├── 6e35d4c19d3e69215947300536be33f2.tar.gz
│   ├── f743368b9ac8adf100cee0e648f20d76.tar.gz
│   └── f962ee2803961e7f7e13fedd54c9dd33.tar.gz
├── aspnet-7-runtime-7.0.110-r0
│   ├── 67e08533ea4be16375c67359497d1eed31ad3ea665a31f60cef411a12e6238f7.dat.tar
│   ├── 67e08533ea4be16375c67359497d1eed31ad3ea665a31f60cef411a12e6238f7.dat.tar.gz
│   ├── 8376820a7031ebe2952c5575414abe2fe8be35f8.ctl.tar.gz
│   └── 8376820a7031ebe2952c5575414abe2fe8be35f8.sig.tar.gz
├── aspnet-7-targeting-pack-7.0.110-r0
│   ├── 169d42ecd42c3da0f5c69853507d96fa5fe6f74c.ctl.tar.gz
│   ├── 169d42ecd42c3da0f5c69853507d96fa5fe6f74c.sig.tar.gz
│   ├── 3c4bf247e4b78fa9944d96c1e6486b29813065bc773ed659b53d52545addf662.dat.tar
│   └── 3c4bf247e4b78fa9944d96c1e6486b29813065bc773ed659b53d52545addf662.dat.tar.gz
...

We don't cache signing keys at all, but we could easily do the same etag-based caching we do for APKINDEX:

$ curl -s -I https://packages.wolfi.dev/os/wolfi-signing.rsa.pub | grep etag:
etag: "efbc77397d26fd228849b6a4b7763ec4"

E.g. something like:

$ tree
.
├── wolfi-signing
│   └── efbc77397d26fd228849b6a4b7763ec4.rsa.pub
└── x86_64
    ├── APKINDEX
    │   └── f962ee2803961e7f7e13fedd54c9dd33.tar.gz
...

Assuming we do this (perhaps under keys/$path/$etag), we have everything we would need to do the whole build offline.

As a first pass, the simplest option would be to list the entries in the corresponding cache directory and use the file with the most recent ModTime.

This makes me think we should probably start doing garbage collection on old entries (especially APKINDEX), but let's ignore that for now.

Another option would be having a symlink (perhaps latest) that gets updated to point to the most recently cached item. It would be pretty interesting to be able to go back in time to a previously cached APKINDEX and build at that point. Let's ignore this option for now and just use the latest modtime.

UX

This doesn't seem like something we want to do automatically, so let's start with an --offline flag. (I'll keep this hidden at first for testing, but if we like it, we should unhide it and start supporting it.)

If you pass the --offline flag, we'll only consult the cache for all dependencies.

If there is a cache miss, we will fail with an error rather than fetching from upstream.

We may want to introduce some commands that allow prefetching a package or index to prepare apko's cache for an offline mode: chainguard-dev/terraform-provider-apko#134

Alternatives Considered

Instead of --offline being a bool, we could do something like --offline=open or --offline=closed to indicate whether we want to fail open or closed. With --offline=open, we would just consult the cache as a source of truth before hitting upstream, which would let us trade off some consistency for availability and latency. If you're building a ton of images, this seems ideal.

Note that it is already entirely possible to point apko at a local directory (only), but it's a bit of a pain to modify your config yaml in order to make that work, and I'm particularly lazy. It might be straightforward to have offline mode just create a symlink forest that points into the cache?