diff --git a/docs/apko_file.md b/docs/apko_file.md index 555e73501..750cc1c1b 100644 --- a/docs/apko_file.md +++ b/docs/apko_file.md @@ -25,7 +25,7 @@ environment: ``` Running `apko build` on this file will produce a tar file containing an Alpine base container image. -The image can be used by container runtimes (for example, running `docker load image.tar` will add +The image can be used by container runtimes (for example, running `docker load < image.tar` will add the image to Docker). The command `apko publish` can also be used to directly push the image to an image registry. diff --git a/docs/build-process.md b/docs/build-process.md index ce6b0cecf..e769f578c 100644 --- a/docs/build-process.md +++ b/docs/build-process.md @@ -5,7 +5,7 @@ The entire build is configured from a declarative file `apko.yaml`, which does n commands. Instead, all content is generated from installing `apk` packages. The build process is driven by the implementation of the `apko build` command, specifically -[`BuildCmd()`](../internal/cli/build.go#L104). +[`BuildCmd()`](../internal/cli/build.go#L142). The entire build process involves laying out the desired files in a temporary working directory, and then packaging that working directory as an OCI filesystem layer `.tar.gz`. With that layer file in hand, @@ -14,44 +14,40 @@ it can be packaged into an OCI image, and an SBoM can be created. The process is as follows: 1. Create a temporary working directory. -1. Create a [`build.Context`](../pkg/build/build.go#L37-45). This `Context` contains: - * The path to the config file, default to `apko.yaml` - * The parsed config file into an internal structure [`ImageConfiguration`](../pkg/build/types/types.go#L55-83) - * The [`buildImplementation`](../pkg/build/build_implementation.go#L43-59), which is the engine responsible for executing the actual build - * The [`Executor`](../pkg/exec/exec.go#L26-31), which handles external command execution by the `buildImplementation` +2. Create a [`build.Context`](../pkg/build/build.go#L52-61). This `Context` contains: + * The parsed config file into an internal structure [`ImageConfiguration`](../pkg/build/types/types.go#L150-199) * The [`s6.Context`](../pkg/s6/s6.go#L23-26), which contains configuration for optionally installing the s6 supervisor to manage the process in the container * Build-time options -1. Refresh the `build.Context`, which sets initialization and runtime parameters, such as isolation, working directory, the executor and the s6 context. -1. Build the layer in the working directory, the heart of the build, calling [`build.Context.BuildLayer()`](../pkg/build/build.go#L80-109). This results in the entire laid out filesystem packaged up into a `.tar.gz` file. More detail on this follows later in this document. -1. Generate an SBoM. -1. Generate an OCI image tar file from the single layer `.tar.gz` file in [`oci.BuildImageTarballFromLayer()`](../pkg/build/oci/oci.go#L285). +3. Refresh the `build.Context`, which sets initialization and runtime parameters, such as isolation, working directory, the executor and the s6 context. +4. Build the layer in the working directory, the heart of the build, calling [`build.Context.BuildLayer()`](../pkg/build/build.go#L117-135). This results in the entire laid out filesystem packaged up into a `.tar.gz` file. More detail on this follows later in this document. +5. Generate an SBoM. +6. Generate an OCI image tar file from the single layer `.tar.gz` file in [`oci.BuildImageTarballFromLayer()`](../pkg/build/oci/image.go#L190). ## Layer Build As described above, after everything is setup, the actual build occurs inside the working directory. -The build is in [`build.Context.BuildLayer()`](../pkg/build/build.go#L80-109), which consists of: +The build is in [`build.Context.BuildLayer()`](../pkg/build/build.go#L117-135), which consists of: 1. `Context.BuildImage()`: building the image -1. `Context.GenerateSBOM()` optionally generate the SBoM -The actual building of the image via `BuildImage()` just wraps [`buildImage()`](../pkg/build/build_implementation.go#L195-247). +The actual building of the image via `BuildImage()` just wraps [`buildImage()`](../pkg/build/build_implementation.go#L154-246). It involves several steps: 1. Validate the image configuration. This includes setting defaults. -1. Initialize the apk. This involves setting up the various apk directories inside the working directory. -1. Add additional tags for apk packages. -1. `MutateAccounts()`: Create users and groups. -1. Set file and directory permissions. -1. Set the symlinks for busybox, as busybox is a single binary which determines what action to take based on the invoked path. -1. Update ldconfig. -1. Create the `/etc/os-release` file. -1. If s6 is used for supervision, install it and create its configuration files. +2. Initialize the apk. This involves setting up the various apk directories inside the working directory. +3. Add additional tags for apk packages. +4. `MutateAccounts()`: Create users and groups. +5. Set file and directory permissions. +6. Set the symlinks for busybox, as busybox is a single binary which determines what action to take based on the invoked path. +7. Update ldconfig. +8. Create the `/etc/os-release` file. +9. If s6 is used for supervision, install it and create its configuration files. Note that all of the steps involve some file manipulation. * In the case of simply laying out files or changing permissions, this is straightforward and performed in the working directory. -* In the case of apk commands, it uses the [pkg/apk/impl](../pkg/apk/impl/) implementation to lay out files directly. +* In the case of apk commands, it uses the [pkg/apk/apk/implementation](../pkg/apk/apk/implementation.go) implementation to lay out files directly. * In the case of `chown`/`chmod`, if it cannot do so directly - either because the underlying filesystem does not support it or because it is not running as root - it ignores the errors and keeps track of the intended ownership and permissions, adding them to the final layer tar stream. * In the case of `ldconfig`, it replicates the equivalent functionality by parsing the library ELF headers and creating the symlinks. * In the case of `busybox`, it creates symlinks to the busybox binary, based on a fixed list. diff --git a/pkg/build/build.go b/pkg/build/build.go index 31fc52dda..24a055422 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -45,7 +45,7 @@ import ( ) // Context contains all of the information necessary to build an -// OCI image. Includes the configurationfor the build, +// OCI image. Includes the configuration for the build, // the path to the config file, the executor for root jails and // architecture emulation, the s6 supervisor to add to the image, // build options, and the `buildImplementation`, which handles the actual build.