chainguard-dev / apko

Build OCI images from APK packages directly without Dockerfile
https://apko.dev
Apache License 2.0
1.16k stars 115 forks source link

Question: Possible to build an OCI image from a base? #806

Open ChrisJBurns opened 1 year ago

ChrisJBurns commented 1 year ago

Currently, with Dockerfiles you can just use a base image and add more stuff that you want.

Example:

FROM cgr.dev/chainguard/wolfi-base # can be any image

apk add custom-package

Is this possible via apko? Are we able to use images already as a base and just extend from them? Or is it required to build the images from scratch? Of course, this applied to any image.

jonjohnsonjr commented 1 year ago

This isn't currently supported, but it wouldn't be impossible to implement... just a matter of priorities 😄

ChrisJBurns commented 1 year ago

@jonjohnsonjr Well if I'm being completely honest, my issue was 100% a shot in the dark as I had a feeling it went against the fundamental principles of what apko is 😄 . However if it is actually something that folks agree would be a feature they're happy apko supports then (providing it's doable by a first time contributor) I don't mind tackling it as a first case? I realllllllllyy like apko, and want as many people to use it as possible, but one of the biggest pushbacks I'm getting from people at the moment is that you have to build an image completely from scratch with existing apk's. So if we could offer some sort of base functionality that allows us to build on top of an existing image, that would be great. - again, providing this is in-line with the Apko design principles?! 😄

jesseops commented 1 year ago

@ChrisJBurns I came across this and the idea that came to mind was to use a remote include on the desired base apko configuration. I think this is intended to provide the solution you're looking for, where the common base can be inherited by multiple images.

I tried this out locally and it worked:

Create config inheriting from the "base", eg at extend-wolfi-base.yaml


include: github.com/chainguard-dev/apko/examples/wolfi-base.yaml@main

contents:
  packages:
    - curl

Build, import, test:

apko build extend-wolfi-base.yaml local/test-extends-wolfi-base output.tar --arch=amd64 \
  && docker load < output.tar \
  && docker run --rm local/test-extends-wolfi-base:latest-amd64 curl -Ls https://httpbin.org/html

The output confirms it's working:

ℹ️            | loading config file: extend-wolfi-base.yaml
ℹ️  x86_64    | including github.com/chainguard-dev/apko/examples/wolfi-base.yaml@main for configuration
⚠️  x86_64    | remote configurations are an experimental feature and subject to change.
ℹ️  x86_64    | Building images for 1 architectures: [amd64]
ℹ️  x86_64    | building tags [local/test-extends-wolfi-base]
ℹ️            | loading config file: extend-wolfi-base.yaml
ℹ️  x86_64    | including github.com/chainguard-dev/apko/examples/wolfi-base.yaml@main for configuration
...
ℹ️  x86_64    | generating supervision tree
ℹ️  x86_64    | finished building filesystem in /tmp/apko-384229132/x86_64
ℹ️  x86_64    | built image layer tarball as /tmp/apko-384229132/image/apko-x86_64.tar.gz
ℹ️  x86_64    | building image from layer
ℹ️  x86_64    | OCI layer digest: sha256:320326458526624459e26f920923e62d96c030cd623ccc292168b399c9bc3352
ℹ️  x86_64    | OCI layer diffID: sha256:f9625b6e4a652027895306ccf8a42dfbf33b27f955a3f41560fc71f2a0a026d8
ℹ️  x86_64    | built index file as /tmp/apko-temp-3631822497/index.json
INFO[0003] Generating arch image SBOMs                  
ℹ️  x86_64    | Generating index SBOM
INFO[0003] Final index tgz at: output.tar               
Loaded image: local/test-extends-wolfi-base:latest-amd64
<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
      <h1>Herman Melville - Moby-Dick</h1>

      <div>
...

Hopefully I'm not missing something where this isn't a helpful method to accomplish what you're needing.

kaniini commented 1 year ago

Yeah the preferred outcome is to use the include: directive, but if that doesn't solve the problem, we can talk about extending layers I guess.

ChrisJBurns commented 1 year ago

Would you be able to use include with any image? for example include: busybox ?

ChrisJBurns commented 1 year ago

I should add a bit more detail to be more clear. Are we able to use include to reference other Docker images, or does it have to point to an exist apko configuration file. I think the latter is the case. So I guess the next question is would it be a good idea to offer another field that allows a user to basically take an image from Dockerhub (or any image registry) as a base and build on it.

For example

include: docker.io/busybox
contents:
  packages:
    - curl
    - another-package

Which downloads the busybox image from Docker registry, and then builds on top of it and installs the curl and another-package into it, eventually creating an image. The equivalent in a Dockerfile would just be:

FROM docker.io/busybox
apk add curl another-package

So I guess it's the apko using existing images instead of apko using other apko files as a base.

kaniini commented 1 year ago

No, apko is not designed to do that, it very much is based on the assumption that it is generating the base image.

imjasonh commented 8 months ago

I think we'd still be interested in supporting this use case, but need to dedicate some more time to thinking through how to express it in the configs.

Since this issue was opened, apko has started being consumed as a library in other tools like Bazel's rules_apko, and the Terraform provider, both of which could benefit from having some concept of appending contents to a base image (those being apko-built themselves, in both cases).

If folks have ideas about how they'd like to express appending to a base image in this thread, we can keep the conversation going. I don't think we should expand the use of include: to do this, since that currently means "augment this config with the config described at <file path>", and it might be confusing if I happen to have a file path matching docker.io/foo/bar for whatever reason.

ChrisJBurns commented 7 months ago

@imjasonh Completely agree, definitely don't want to overload the current include capability. Perhaps existingImage or ociBase something to distinguish that there is a difference between using an apko base image and a non-apko base image.