bootc-image-builder

repository·main·Indexed 19 days ago

https://github.com/osbuild/bootc-image-builder

A tool for creating bootable disk images (such as QCOW2, ISO, or AMI) from bootc container images, primarily used for Fedora and CentOS bootc workflows. It supports privileged and rootless builds via Podman, image customization through TOML/JSON build configs for users, kernel arguments, and filesystems, and provides functionality to upload images to cloud providers.

Tokens
9.1K
Snippets
34
Records
41
Agent score
66%

What's inside bootc-image-builder

  1. Requirements for pxe-tar-xz and bootc-installer image types

    main

    Certain image types require specific configurations in the source container image.

    pxe-tar-xz

    The source container must have dracut-live and squashfs-tools installed, and the initramfs must be rebuilt with the dmsquash-live module.

    bootc-installer

    The source container must contain Anaconda. You must also provide the --bootc-installer-payload-ref argument, which points to a container reference containing the payload to be installed by Anaconda.

    # Example Containerfile for bootc-installer source
    FROM your-favorite-bootc-container:latest
    RUN dnf install -y \
         anaconda \
         anaconda-install-env-deps \
         anaconda-dracut \
         dracut-config-generic \
         dracut-network \
         net-tools \
         squashfs-tools \
         grub2-efi-x64-cdboot \
         python3-mako \
         lorax-templates-* \
         biosdevname \
         prefixdevname \
         && dnf clean all
    
    # Required for Fedora 43+ to ensure EFI files are in the correct location
    RUN mkdir -p /boot/efi && cp -ra /usr/lib/efi/*/*/EFI /boot/efi
    
    # Required for lorax compatibility on some images
    RUN mkdir /var/mnt
  2. Create a build config for image customization

    main

    A build config is a TOML or JSON file used to apply customizations to the resulting image. Customizations must be defined under a customizations object.

    Ways to provide the config:

    1. File mapping: Map a local file to /config.toml inside the container using a volume (e.g., -v ./config.toml:/config.toml:ro).
    2. Stdin: Pass JSON configuration via stdin using the --config - flag.
    3. Embedded: Images can embed a config file at /usr/lib/bootc-image-builder/config.json or config.toml. If present, these are used by default for filesystem or disk customizations if no other customizations are specified.
    sudo podman run \
        --rm \
        -it \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v ./config.toml:/config.toml:ro \
        -v ./output:/output \
        -v /var/lib/containers/storage:/var/lib/containers/storage \
        quay.io/centos-bootc/bootc-image-builder:latest \
        --type qcow2 \
        quay.io/centos-bootc/centos-bootc:stream9
  3. Understand the code layout

    main

    The project structure is organized as follows:

    • Go Source Code: Located in the ./bib directory. The project uses the images library internally to generate bootc images.
    • Integration Tests: Located in the ./test directory and written using pytest.
  4. Run a resulting QCOW2 image on Linux or macOS

    main

    Once the image is built, you can run it using QEMU.

    Linux (x86_64)

    Use qemu-system-x86_64 with KVM acceleration or virt-install for managed virtualization.

    macOS (aarch64)

    Use qemu-system-aarch64 with hvf acceleration (assuming QEMU was installed via Homebrew).

    # Linux: qemu-system-x86_64
    qemu-system-x86_64 \
        -M accel=kvm \
        -cpu host \
        -smp 2 \
        -m 4096 \
        -bios /usr/share/OVMF/OVMF_CODE.fd \
        -serial stdio \
        -snapshot output/qcow2/disk.qcow2
    
    # macOS: qemu-system-aarch64
    qemu-system-aarch64 \
        -M accel=hvf \
        -cpu host \
        -smp 2 \
        -m 4096 \
        -bios /opt/homebrew/Cellar/qemu/8.1.3_2/share/qemu/edk2-aarch64-code.fd \
        -serial stdio \
        -machine virt \
        -snapshot output/qcow2/disk.qcow2
  5. Run integration tests

    main

    Integration tests are written in pytest and are located in the ./test directory. These tests involve building and booting multiple images and can take approximately 45 minutes to complete.

    Prerequisites: Ensure you have the necessary test dependencies installed (such as podman and qemu).

    To run the tests, change into the bootc-image-builder root directory and use one of the following commands:

    • For concise output: pytest
    • For full, verbose output: pytest -s -vv
    # For concise output
    $ pytest
    
    # For full output
    $ pytest -s -vv
  6. Build the bootc-image-builder container locally

    main

    To build the builder image itself using Podman, run the build command from the repository root. It is recommended to run this as root to avoid permission issues during the image building process.

    sudo podman build --tag bootc-image-builder .
  7. Build the bootc-image-builder development container

    main

    To work on the multiple components of bootc-image-builder using locally checked out development versions, use the Containerfile located in the devel/ directory. This process requires providing two additional build contexts via --build-context, pointing to the root source directories of the following projects:

    1. osbuild/osbuild
    2. osbuild/images
    3. osbuild/bootc-image-builder (the current repository)

    Important: The osbuild RPM build will fail if there are uncommitted changes in the osbuild repository.

    podman build --file=devel/Containerfile --build-context=osbuild=$HOME/src/osbuild --build-context=images=$HOME/src/images -t bootc-image-builder:devel .
  8. Upload images to Amazon Machine Images (AMIs)

    main

    To automatically upload a disk image to AWS as an AMI, use the --type ami type along with the required AWS flags.

    Requirements:

    1. Flags: You must specify --aws-ami-name, --aws-bucket, and --aws-region together. If any are missing, the image is exported to the local output directory instead of being uploaded.
    2. S3 Bucket: The target bucket must already exist in the specified region.
    3. IAM Permissions: The vmimport service role in your AWS account must have s3:ListAllMyBuckets, s3:GetBucketAcl, and s3:DeleteObject permissions for the intermediate storage bucket.

    AWS Credentials: You can provide credentials by:

    • Mounting your local AWS credentials directory (e.g., -v $HOME/.aws:/root/.aws:ro) and setting --env AWS_PROFILE=default.
    • Using --env-file to pass a file containing AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.
    • Injecting all AWS configuration via --env AWS_*.
    $ cat aws.secrets
    AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
    AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
    
    $ sudo podman run \
      --rm \
      -it \
      --privileged \
      --pull=newer \
      --security-opt label=type:unconfined_t \
      -v /var/lib/containers/storage:/var/lib/containers/storage \
      --env-file=aws.secrets \
      quay.io/centos-bootc/bootc-image-builder:latest \
      --type ami \
      --aws-ami-name centos-bootc-ami \
      --aws-bucket centos-bootc-bucket \
      --aws-region us-east-1 \
      quay.io/centos-bootc/centos-bootc:stream9
  9. Perform live debugging of builds

    main

    To debug a failing build process, you can run bootc-image-builder in an interactive mode and then invoke osbuild directly to inspect the build stages.

    1. Start an interactive session: Run bootc-image-builder with the --entrypoint bash flag to maintain a persistent shell inside the container.
    2. Generate a manifest: Inside the container shell, generate a manifest for your target image and save it to a file: bootc-image-builder manifest <IMAGE_URL> > /tmp/manifest.json
    3. Invoke osbuild directly: Use the osbuild command with the generated manifest. You can use flags like --break to stop the build at a specific stage for inspection.

    Example command for direct osbuild invocation:

    osbuild --cache-max-size unlimited --export qcow2 --store /store --output-directory /output /tmp/manifest.json
  10. Configure passwordless sudo in a bootc image

    main

    By default, the quay.io/centos-bootc/centos-bootc:stream9 image does not have passwordless sudo configured. If you create a user without a password in your build config, sudo will not work. To enable passwordless sudo for the wheel group, add a file to /etc/sudoers.d/ in your base container image.

    FROM quay.io/centos-bootc/centos-bootc:stream9
    ADD wheel-passwordless-sudo /etc/sudoers.d/wheel-passwordless-sudo

    Content of wheel-passwordless-sudo:

    %wheel ALL=(ALL) NOPASSWD: ALL
  11. Install bootc-image-builder

    main

    To use bootc-image-builder, you must have podman installed on your system.

    • Linux: Install via your system's package manager.
    • macOS/Windows: Install via Podman Desktop.
    • Virtualization: If you intend to run the resulting images, install qemu.

    macOS Specific Setup: On macOS, the podman machine must be running in rootful mode:

    $ podman machine stop
    $ podman machine set --rootful
    $ podman machine start
    podman machine stop
    podman machine set --rootful
    podman machine start