Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: additional details around bootc images, install #195

Merged
merged 2 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions docs/bootc-images.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ nav_order: 2
# "bootc compatible" images

At the current time, it does not work to just do:
```

```Dockerfile
FROM fedora
RUN dnf -y install kernel
```

or
```

```Dockerfile
FROM debian
RUN apt install kernel
```
Expand All @@ -30,29 +33,42 @@ for generating base images currently requires running
through ostree tooling to generate an "ostree commit"
which has some special formatting in the base image.

The two most common ways to do this are to either:

1. compose a compatible OCI image directly via [`rpm-ostree compose image`](https://coreos.github.io/rpm-ostree/container/#creating-base-images)
1. encapsulate an ostree commit using `rpm-ostree compose container-encapsulate`

The first method is most direct, as it streamlines the process of
creating a base image and writing to a registry. The second method
may be preferable if you already have a build process that produces `ostree`
commits as an output (e.g. using [osbuild](https://www.osbuild.org/guides/image-builder-on-premises/building-ostree-images.html)
to produce `ostree` commit artifacts.)

The requirement for both methods is that your initial treefile/manifest
**MUST** include the `bootc` package in list of packages included in your compose.

However, the ostree usage is an implementation detail
and the requirement on this will be lifted in the future.

For example, the [rpm-ostree compose image](https://coreos.github.io/rpm-ostree/container/#creating-base-images)
tooling currently streamlines creating base images, operating just
on a declarative input and writing to a registry.

# Deriving from existing base images

However, it's important to emphasize that from one
It's important to emphasize that from one
of these specially-formatted base images, every
tool and technique for container building applies!
In other words it will Just Work to do
```

```Dockerfile
FROM <bootc base image>
RUN dnf -y install foo && dnf clean all
RUN dnf -y install foo && dnf clean all
```

You can then use `podman build`, `buildah`, `docker build`, or any other container
build tool to produce your customized image. The only requirement is that the
container build tool supports producing OCI container images.

## Using the `ostree container commit` command

As an opt-in optimization today, you can also add `ostree container commit`
as part of your `RUN` invocations. This will perform early detection
as part of your `RUN` invocations. This will perform early detection
of some incompatibilities but is not a strict requirement today and will not be
in the future.


80 changes: 44 additions & 36 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
nav_order: 2
---

# `bootc install`
# Installing "bootc compatible" images

A key goal of the bootc project is to think of bootable operating systems
as container images. Docker/OCI container images are just tarballs
Expand All @@ -17,51 +17,63 @@ The Linux kernel (and optionally initramfs) is embedded in the container image;
is `/usr/lib/modules/$kver/vmlinuz`, and the initramfs should be in `initramfs.img`
in that directory.

The `bootc install` command bridges the two worlds of a standard runnable OCI image
and a bootable system by running tooling
logic embedded in the container image to create the filesystem and
bootloader setup dynamically, using tools already embedded in the container
image. This requires running the container via `--privileged`; it uses
the running Linux kernel to write the file content from the running container image;
not the kernel inside the container.
The `bootc install` and `boot install-to-filesystem` commands bridge the two worlds
of a standard, runnable OCI image and a bootable system by running tooling logic embedded
in the container image to create the filesystem and bootloader setup dynamically.
This requires running the container via `--privileged`; it uses the running Linux kernel
on the host to write the file content from the running container image; not the kernel
inside the container.

However nothing *else* (external) is required to perform a basic installation
to disk. This is motivated by experience gained from the Fedora CoreOS
However, nothing *else* (external) is required to perform a basic installation
to disk. (The one exception to host requirements today is that the host must
have `skopeo` installed. This is a bug; more information in
[this issue](https://github.com/containers/bootc/issues/81).)

This is motivated by experience gained from the Fedora CoreOS
project where today the expectation is that one boots from a pre-existing disk
image (AMI, qcow2, etc) or use [coreos-installer](https://github.com/coreos/coreos-installer)
image (AMI, qcow2, etc) or uses [coreos-installer](https://github.com/coreos/coreos-installer)
for many bare metal setups. But the problem is that coreos-installer
is oriented to installing raw disk images. This means that if
one creates a custom derived container, then it's required for
one to also generate a raw disk image to install. This is a large
ergonomic hit.

With `bootc install`, no extra steps are required. Every container
With the `bootc` install methods, no extra steps are required. Every container
image comes with a basic installer.

## Executing `bootc install`

The installation command must be run from the container image
The two installation commands allow you to install the container image
either directly to a block device (`bootc install`) or to an existing
filesystem (`bootc install-to-filesystem`).

The installation commands **MUST** be run **from** the container image
that will be installed, using `--privileged` and a few
other options.
other options. This means you are (currently) not able to install `bootc`
to an existing system and install your container image. Failure to run
`bootc` from a container image will result in an error.

Here's an example:
Here's an example of using `bootc install` (root/elevated permission required):
Copy link
Member

@vrothberg vrothberg Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great to have copy-paste examples in the docs. I have encountered a number of issues trying to bootc-install in a pet VM.
"Boot this image, then do ..., then do a podman-run ...bootc install ...".


```sh
```bash
podman run --rm --privileged --pid=host --security-opt label=type:unconfined_t <image> bootc install --target-no-signature-verification /path/to/disk
```

Note that while `--privileged` is used, this command will not perform any
destructive action on the host system. Among other things, `--privileged`
makes sure that all host devices are mounted into container. `/path/to/disk` is
the host's block device `<image>` will be installed on.
the host's block device where `<image>` will be installed on.

The `--pid=host --security-opt label=type:unconfined_t` today
make it more convenient for bootc to perform some privileged
operations; in the future these requirement may be dropped.

Jump to the section for [`install-to-filesystem`](#more-advanced-installation) later
in this document for additional information about that method.

### "day 2" updates, security and fetch configuration

Note that by default the `bootc install` path will find the pull specification used
By default the `bootc install` path will find the pull specification used
for the `podman run` invocation and use it to set up "day 2" OS updates that `bootc update`
will use.

Expand All @@ -74,7 +86,7 @@ By default, the installation process will verify that the container (representin
can fetch its own updates. A common cause of failure here is not changing the security settings
in `/etc/containers/policy.json` in the target OS to verify signatures.

If you are pushing an unsigned image, you must specify `bootc install --target-no-signature-verification`.
If you are pushing an unsigned image, you **MUST** specify `bootc install --target-no-signature-verification`.

Additionally note that to perform an install with a target image reference set to an
authenticated registry, you must provide a pull secret. One path is to embed the pull secret into
Expand All @@ -84,26 +96,21 @@ in that case you will need to specify `--skip-fetch-check`.

### Operating system install configuration required

The container image must define its default install configuration. For example,
The container image **MUST** define its default install configuration. For example,
create `/usr/lib/bootc/install/00-exampleos.toml` with the contents:

```toml
[install]
root-fs-type = "xfs"
```

At the current time, `root-fs-type` is the only available configuration option, and it must be set.
At the current time, `root-fs-type` is the only available configuration option, and it **MUST** be set.

Configuration files found in this directory will be merged, with higher alphanumeric values
taking precedence. If for example you are building a derived container image from the above OS,
you coudl create a `50-myos.toml` that sets `root-fs-type = "btrfs"` which will override the
you could create a `50-myos.toml` that sets `root-fs-type = "btrfs"` which will override the
prior setting.

### Note: Today `bootc install` has a host requirement on `skopeo`

The one exception to host requirements today is that the host must
have `skopeo` installed. This is a bug; more information in [this issue](https://github.com/containers/bootc/issues/81).

## Installing an "unconfigured" image

The bootc project aims to support generic/general-purpose operating
Expand All @@ -128,12 +135,12 @@ the configuration comes from a place *external* to the image.

### Injecting configuration into a custom image

But a new super-power with `bootc` is that you can also easily instead
But a new super-power with `bootc` is that you can also easily
create a derived container that injects your desired configuration,
alongside any additional executable code (packages, etc).
alongside any additional executable code (binaries, packages, scripts, etc).

The expectation is that most operating systems will be designed such
that user state i.e. `/root` and `/home` will be on a separate persistent data store.
that user state i.e. `/root` and `/home` will be on a separate, persistent data store.
For example, in the default ostree model, `/root` is `/var/roothome`
and `/home` is `/var/home`. Content in `/var` cannot be shipped
in the image - it is per machine state.
Expand Down Expand Up @@ -207,15 +214,16 @@ somewhat destructive operation for the existing Linux installation.
Also, because the filesystem is reused, it's required that the target system kernel
support the root storage setup already initialized.

The core command should look like this:
The core command should look like this (root/elevated permission required):

```sh
podman run --rm --privileged -v /:/target --pid=host --security-opt label=type:unconfined_t \
<image> \
bootc install-to-filesystem --replace=alongside /target
```bash
podman run --rm --privileged -v /:/target \
--pid=host --security-opt label=type:unconfined_t \
<image> \
bootc install-to-filesystem --replace=alongside /target
```

At the current time, leftover data in `/` is *not* automatically cleaned up. This can
At the current time, leftover data in `/` is **NOT** automatically cleaned up. This can
be useful, because it allows the new image to automatically import data from the previous
host system! For example, things like SSH keys or container images can be copied
and then deleted from the original.
Loading