Chapter 3. Creating system images with Image Builder command-line interface

Image Builder is a tool for creating custom system images. To control Image Builder and create your custom system images, use the command-line interface which is currently the preferred method to use Image Builder.

3.1. Image Builder command-line interface

Image Builder command-line interface is currently the preferred method to use Image Builder. It offers more functionality than the Web console interface. To use this interface, run the composer-cli command with suitable options and subcommands.

The workflow for the command-line interface can be summarized as follows:

  1. Export (save) the blueprint definition to a plain text file
  2. Edit this file in a text editor
  3. Import (push) the blueprint text file back into Image Builder
  4. Run a compose to build an image from the blueprint
  5. Export the image file to download it

Apart from the basic subcommands to achieve this procedure, the composer-cli command offers many subcommands to examine the state of configured blueprints and composes.

To run the composer-cli command as non-root, user must be in the weldr or root groups.

3.2. Creating an Image Builder blueprint with command-line interface

This procedure describes how to create a new Image Builder blueprint using the command-line interface.

Procedure

  1. Create a plain text file with the following contents:

    name = "BLUEPRINT-NAME"
    description = "LONG FORM DESCRIPTION TEXT"
    version = "0.0.1"
    modules = []
    groups = []

    Replace BLUEPRINT-NAME and LONG FORM DESCRIPTION TEXT with a name and description for your blueprint.

    Replace 0.0.1 with a version number according to the Semantic Versioning scheme.

  2. For every package that you want to be included in the blueprint, add the following lines to the file:

    [[packages]]
    name = "package-name"
    version = "package-version"

    Replace package-name with name of the package, such as httpd, gdb-doc, or coreutils.

    Replace package-version with a version to use. This field supports dnf version specifications:

    • For a specific version, use the exact version number such as 8.30.
    • For latest available version, use the asterisk *.
    • For a latest minor version, use format such as 8.*.
  3. Blueprints can be customized in a number of ways. For this example, Simultaneous Multi Threading (SMT) can be disabled by performing the steps below. For additional customizations available, please see Section 3.7, “Supported Image Customizations”.

    [customizations.kernel]
    append = "nosmt=force"
  4. Save the file as BLUEPRINT-NAME.toml and close the text editor.
  5. Push (import) the blueprint:

    # composer-cli blueprints push BLUEPRINT-NAME.toml

    Replace BLUEPRINT-NAME with the value you used in previous steps.

  6. To verify that the blueprint has been pushed and exists, list the existing blueprints:

    # composer-cli blueprints list
  7. Check whether the components and versions listed in the blueprint and their dependencies are valid:

    # composer-cli blueprints depsolve BLUEPRINT-NAME

3.3. Editing an Image Builder blueprint with command-line interface

This procedure describes how to edit an existing Image Builder blueprint in the command-line interface.

Procedure

  1. Save (export) the blueprint to a local text file:

    # composer-cli blueprints save BLUEPRINT-NAME
  2. Edit the BLUEPRINT-NAME.toml file with a text editor of your choice and make your changes.
  3. Before finishing with the edits, make sure the file is a valid blueprint:

    1. Remove this line, if present:

      packages = []
    2. Increase the version number. Remember that Image Builder blueprint versions must use the Semantic Versioning scheme. Note also that if you do not change the version, the patch component of version is increased automatically.
    3. Check if the contents are valid TOML specifications. See the TOML documentation for more information.

      Note

      TOML documentation is a community product and is not supported by Red Hat. You can report any issues with the tool at https://github.com/toml-lang/toml/issues

  4. Save the file and close the editor.
  5. Push (import) the blueprint back into Image Builder:

    # composer-cli blueprints push BLUEPRINT-NAME.toml

    Note that you must supply the file name including the .toml extension, while in other commands you use only the name of the blueprint.

  6. To verify that the contents uploaded to Image Builder match your edits, list the contents of blueprint:

    # composer-cli blueprints show BLUEPRINT-NAME
  7. Check whether the components and versions listed in the blueprint and their dependencies are valid:

    # composer-cli blueprints depsolve BLUEPRINT-NAME

3.4. Creating a system image with Image Builder in the command-line interface

This procedure shows how to build a custom image using the Image Builder command-line interface.

Prerequisites

  • You have a blueprint prepared for the image.

Procedure

  1. Start the compose:

    # composer-cli compose start BLUEPRINT-NAME IMAGE-TYPE

    Replace BLUEPRINT-NAME with name of the blueprint, and IMAGE-TYPE with the type of image. For possible values, see output of the composer-cli compose types command.

    The compose process starts in the background and the UUID of the compose is shown.

  2. Wait until the compose is finished. Please, notice that this may take several minutes.

    To check the status of the compose:

    # composer-cli compose status

    A finished compose shows a status value FINISHED. Identify the compose in the list by its UUID.

  3. Once the compose is finished, download the resulting image file:

    # composer-cli compose image UUID

    Replace UUID with the UUID value shown in the previous steps.

    Alternatively, you can access the image file directly under the path /var/lib/lorax/composer/results/UUID/.

    You can also download the logs using the composer-cli compose logs UUID command, or the metadata using the composer-cli compose metadata UUID command.

3.5. Basic Image Builder command-line commands

The Image Builder command-line interface offers the following subcommands.

Blueprint manipulation

List all available blueprints
# composer-cli blueprints list
Show a blueprint contents in the TOML format
# composer-cli blueprints show BLUEPRINT-NAME
Save (export) blueprint contents in the TOML format into a file BLUEPRINT-NAME.toml
# composer-cli blueprints save BLUEPRINT-NAME
Remove a blueprint
# composer-cli blueprints delete BLUEPRINT-NAME
Push (import) a blueprint file in the TOML format into Image Builder
# composer-cli blueprints push BLUEPRINT-NAME

Composing images from blueprints

Start a compose
# composer-cli compose start BLUEPRINT COMPOSE-TYPE

Replace BLUEPRINT with name of the blueprint to build and COMPOSE-TYPE with the output image type.

List all composes
# composer-cli compose list
List all composes and their status
# composer-cli compose status
Cancel a running compose
# composer-cli compose cancel COMPOSE-UUID
Delete a finished compose
# composer-cli compose delete COMPOSE-UUID
Show detailed information about a compose
# composer-cli compose info COMPOSE-UUID
Download image file of a compose
# composer-cli compose image COMPOSE-UUID

Related information

  • The composer-cli(1) manual page provides a full list of the available subcommands and options:

    $ man composer-cli
  • The composer-cli command provides help on the subcommands and options:

    # composer-cli help

3.6. Image Builder blueprint format

Image Builder blueprints are presented to the user as plain text in the Tom’s Obvious, Minimal Language (TOML) format.

The elements of a typical blueprint file include:

The blueprint metadata
name = "BLUEPRINT-NAME"
description = "LONG FORM DESCRIPTION TEXT"
version = "VERSION"

Replace BLUEPRINT-NAME and LONG FORM DESCRIPTION TEXT with a name and description for your blueprint.

Replace VERSION with a version number according to the Semantic Versioning scheme.

This part is present only once for the whole blueprint file.

The entry modules describe the package names and matching version glob to be installed into the image.

The entry group describes a group of packages to be installed into the image. Groups categorize their packages in:

  • Mandatory
  • Default
  • Optional

    Blueprints installs the mandatory packages. There is no mechanism for selecting optional packages.

Groups to include in the image
[[groups]]
name = "group-name"

Replace group-name with the name of the group, such as anaconda-tools, widget, wheel or users.

Packages to include in the image
[[packages]]
name = "package-name"
version = "package-version"

Replace package-name with the name of the package, such as httpd, gdb-doc, or coreutils.

Replace package-version with a version to use. This field supports dnf version specifications:

  • For a specific version, use the exact version number such as 8.30.
  • For latest available version, use the asterisk *.
  • For a latest minor version, use format such as 8.*.

Repeat this block for every package to include.

3.7. Supported Image Customizations

A number of image customizations are supported at this time within blueprints. In order to make use of these options, they must be initially configured in the blueprint and imported (pushed) to Image Builder.

Note

These customizations are not currently supported within the accompanying cockpit-composer GUI.

Set the image hostname
[customizations]
hostname = "baseimage"
User specifications for the resulting system image
[[customizations.user]]
name = "USER-NAME"
description = "USER-DESCRIPTION"
password = "PASSWORD-HASH"
key = "PUBLIC-SSH-KEY"
home = "/home/USER-NAME/"
shell = "/usr/bin/bash"
groups = ["users", "wheel"]
uid = NUMBER
gid = NUMBER
Important

To generate the hash, you must install python3 on your system. The following command will install the python3 package.

# yum install python3

Replace PASSWORD-HASH with the actual password hash. To generate the hash, use a command such as:

$ python3 -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'

Replace PUBLIC-SSH-KEY with the actual public key.

Replace the other placeholders with suitable values.

Leave out any of the lines as needed, only the user name is required.

Repeat this block for every user to include.

Group specifications for the resulting system image
[[customizations.group]]
name = "GROUP-NAME"
gid = NUMBER

Repeat this block for every group to include.

Set an existing users ssh key
[[customizations.sshkey]]
user = "root"
key = "PUBLIC-SSH-KEY"
Note

This option is only applicable for existing users. To create a user and set an ssh key, use the User specifications for the resulting system image customization.

Append a kernel boot parameter option to the defaults
[customizations.kernel]
append = "KERNEL-OPTION"
Set the image host name
[customizations]
hostname = "BASE-IMAGE"
Add a group for the resulting system image
[[customizations.group]]
name = "USER-NAME"
gid = "NUMBER"

Only the name is required and GID is optional.

Set the timezone and the Network Time Protocol (NTP) servers for the resulting system image
[customizations.timezone]
timezone = "TIMEZONE"
ntpservers = "NTP_SERVER"

If you do not set a timezone, the system uses Universal Time, Coordinated (UTC) as default. Setting NTP servers is optional.

Set the locale settings for the resulting system image
[customizations.locale]
language = "[LANGUAGE]"
keyboard = "KEYBOARD"

Setting both language and keyboard options is mandatory. You can add multiple languages. The first language you add will be the primary language and the other languages will be secondary.

Set the firewall for the resulting system image
[customizations.firewall]
port = "[PORTS]"

You can use the numeric ports, or theirs names from the /etc/services file to enable or disable lists.

Set which services to enable during the boot time
[customizations.services]
enabled = "[SERVICES]"
disabled = "[SERVICES]"

You can control which services to enable during the boot time. Some image types already have services enabled or disabled so that the image works correctly and this setup cannot be overridden.

Add files from a git repository to your blueprint
[[repos.git]]
rpmname = "_RPM-NAME"
rpmversion = "[RPM-VERSION]"
rpmrelease = "[RPM-RELEASE]"
summary = "[RPM-SUMMARY]"
repo = "[REPO-URL]"
ref = "[GIT-REF]"
destination = "[SERVICES]"

You can use entries to add files from a git repository to the created image.

For example, to create an RPM package named server-config-1.0-1.noarch.rpm, add the following information to your blueprint:

Replace _RPM-NAME with the name of the RPM package to create. This is also the prefix name in the resulting tar archive.

Replace RPM-VERSION with the version of the RPM package, for example, “1.0.0”.

Replace RPM-RELEASE with the version of the RPM package release, for example, “1”.

Replace RPM-SUMMARY with the summary string for the RPM package.

Replace REPO-URL with the URL of the get repository to clone and create the archive from it.

Replace GIT-REF with the git reference to check out, for example, origin/branch-name, git tag, or git commit hash.

Replace SERVICES with the path to install the directory of the git repository when installing the RPM package.

As a consequence, the git repository  you provided is cloned, the specified git reference is checked out and an RPM package is created to install the files to a destination path, for example, /opt/server/. The RPM includes a summary with the details of the repository and reference used to create it. The RPM package is also included in the image build metadata.

Note

Each time a build starts, it clones the repository. If you refer to a repository with a large amount of history, it might take a while to clone and use a significant amount of disk space. Also, the clone is temporary and is removed once the RPM package is created.

3.8. Installed Packages

When you create a system image using Image Builder, by default, the system installs a set of base packages. The base list of packages are the members of the comps core group.

Table 3.1. Default packages to support image type creation

Image typeDefault Packages

alibaba.ks

kernel, selinux-policy-targeted, cloud-init

ami.ks

kernel, selinux-policy-targeted, chrony, cloud-init

ext4-filesystem.ks

policycoreutils, selinux-policy-targeted, kernel

google.ks

kernel, selinux-policy-targeted

live-iso.ks

isomd5sum, kernel, dracut-config-generic, dracut-live, system-logos, selinux-policy-targeted

openstack.ks

kernel, selinux-policy-targeted

partitioned-disk.ks

kernel, selinux-policy-targeted

qcow2.ks

kernel, selinux-policy-targeted

tar.ks

policycoreutils, selinux-policy-targeted

vhd.ks

kernel, selinux-policy-targeted, chrony, WALinuxAgent, python3, net-tools, cloud-init, cloud-utils-growpart, gdisk

vmdk.ks

kernel, selinux-policy-targeted, chrony, open-vm-tools

Note

When you add additional components to your blueprint, you must make sure that the packages in the components you added do not conflict with any other package components, otherwise the system fails to solve dependencies. As a consequence, you are not able to create your customized image.

Additional resources

3.9. Enabled Services

When you configure the custom image, the services enabled are the defaults services for the RHEL8 release you are running lorax-composer from, additionally the services enabled for specific image types.

For example, the .ami image type enables the services sshd, chronyd and cloud-init and without these services, the custom image does not boot.

Table 3.2. Enabled services to support image type creation

Image typeEnabled Services

alibaba.ks

sshd,cloud-init

ami.ks

No default service

ext4-filesystem.ks

No default service

google.ks

No default service

live-iso.ks

NetworkManager

openstack.ks

sshd, cloud-init, cloud-init-local, cloud-config, cloud-final

partitioned-disk.ks

No default service

qcow2.ks

No default service

tar.ks

No default service

vhd.ks

sshd, chronyd, waagent, cloud-init, cloud-init-local, cloud-config, cloud-final

vmdk.ks

sshd, chronyd, vmtoolsd

Note: You can customize which services to enable during the system boot. However, for image types with services enabled by default, the customization does not override this feature.

Additional resources

3.10. Disks and Partitions Configuration using Image Builder

Image Builder does not allow disks to be partitioned. The output types that have a partitioned disk will have a single partition and additionally any platform-specific partitions that are required to boot the system image. For example, qcow2 image type has a single root partition, and possibly a platform specific boot partition - like PReP for PPC64 system - that the image requires to boot.