Skip to content

Containerizing applications

An alternative to packaging your software with RPM is to install your application or service in a Linux container. Deploying applications as containers can be advantageous because the container isolates the application from the OS, as well as from other containers. This means that you can build the application against a different base OS that is not necessarily compatible with AutoSD, with the exception of the kernel application binary interface (ABI). With this framework, you can have multiple applications that use different environments running on a single system.

In addition, containers have other advantages, such as the ability for each container to use different versions of dependencies and the improved robustness, security, and flexibility that comes from the kernel-level application isolation. This isolation forms the mixed-criticality architecture of the AutoSD application environment.

Mixed-criticality workloads

The isolation aspects of containers support separated services and align with the requirement for well-defined interfaces between containers.

Building a container image for your software

A container image is a lightweight, standalone software package that includes the code, tools, libraries, and settings required to run a piece of software. The configuration for a container image is stored in a file called a Containerfile.

Prerequisites

  • Podman
  • An RPM package (auto-apps) in an RPM package repository (/var/tmp/my_repo)

Procedure

  1. Create a Containerfile that includes the RPM package that you created in Packaging your application source code with RPM:

    FROM quay.io/fedora/fedora:40
    
    COPY my_repo /tmp/my_repo
    
    RUN ls -l /tmp && ls -l /tmp/my_repo
    
    RUN dnf install -y /tmp/my_repo/x86_64/auto-apps-0.1*.rpm && dnf clean all
    
  2. Copy the RPM repository from /var/tmp/my_repo to the same directory where you have created the Containerfile file:

    $ cp -r /var/tmp/my_repo .
    
  3. Run podman build in the same directory as your Containerfile to build the container image, and name the container image auto-apps:

    $ sudo podman build -t localhost/auto-apps:latest -f Containerfile
    
  4. Start a container from your auto-apps container image,

    $ sudo podman run -it auto-apps
    
  5. From within the running container, verify that your RPM package is present.

    $ rpm -q auto-apps
    

    If the auto-apps RPM was embedded successfully in the container, the output of the rpm -q command displays the version of your package:

    $ auto-apps-0.1-1.fc40.x86_64
    

Now that you have a functional auto-apps container image, you can embed your containerized applications in the OS image with OSBuild.

Embedding containerized applications in an OS image

After creating a container image for your application, you can embed it in an OS image.

Depending on your needs, you can use one of two methods to embed the container image in your operating system image:

  • Recommended method: Create the container image and add it to a remote container registry. Then, pull the container image from the remote registry to include in the OS image. This method is the only reliable, reproducible method for OS image builds and is therefore recommended.
  • Development method: Create the container image and add it to a local RPM repository. Then, pull the container image from your local repository to include in the OS image. Only use this method to build OS images for development and experimentation purposes.

Embedding container images from a remote registry

You can download and embed containerized applications from a remote container image registry when you build an AutoSD operating system (OS) image. Doing so makes the containerized application available for use from within the AutoSD OS after the system boots.

When you use this method, OSBuild pulls a container from a remote container image registry at build time and embeds it in the AutoSD image.

Important

If you want to include containerized applications in an OS image, pulling containers from a secure remote registry is the only reliable, reproducible, and recommended method for production OS image builds. Although you can also containerize applications locally and embed them from local storage when building an OS image, doing so is not the method recommended for building the OS image and is meant only for development or experimental purposes.

Prerequisites

Sample procedure

This sample procedure explains how to create an automotive image builder manifest and build an AutoSD operating system image in the qcow2 format that you can boot in a QEMU virtual machine.

The resulting AutoSD OS image will include a containerized CentOS 10 application image pulled from the quay.io remote container image registry and installed to /usr/share/containers/storage in the AutoSD OS.

Note that you can customize the script and the manifest to pull your own containerized application images from any image registry to which you have access.

  1. Create a build manifest file named container_remote.aib.yml:

    $ touch container_remote.aib.yml
    
  2. Open the container_remote.aib.yml file in a text editor, add the following YAML code, and save the file:

    Sample manifest for embedding remote container images
    # hosted in a remote container registry
    
    name: container_remote
    
    content:
      repos:
        - id: epel
          baseurl: https://dl.fedoraproject.org/pub/epel/9/Everything/$arch/
      rpms:
        - podman
        # For testing the image only:
        - openssh-server
        - openssh-clients
    
      container_images:
        - source: quay.io/centos/centos
          tag: stream10-development
          name: localhost/cs10
    
      # Required for testing the image only:
      systemd:
        enabled_services:
          # Enable ssh daemon
          - sshd.service
    
    auth:
      # "password"
      root_password: $6$xoLqEUz0cGGJRx01$H3H/bFm0myJPULNMtbSsOFd/2BnHqHkMD92Sfxd.EKM9hXTWSmELG8cf205l6dktomuTcgKGGtGDgtvHVXSWU.
      # Required for testing the image only:
      sshd_config:
        PasswordAuthentication: true
        PermitRootLogin: true
    
  3. Export the value of your hardware architecture to a temporary variable:

    $ export arch=$(arch)
    
  4. Run the automotive-image-builder tool to build an OS image that embeds the remote containerized application:

    $ sudo automotive-image-builder \
        --verbose \
        --include=/var/lib/containers/storage/ \
        build \
        --distro autosd \
        --target qemu \
        --mode image \
        --build-dir=_build \
        --export qcow2 \
        container_remote.aib.yml \
        container_remote.$arch.qcow2
    

    Note

    You can customize the automotive-image-builder command to set other options for distro name, mode, target, and export format.

  5. Verify that the script has created an AutoSD image file named container_remote.<arch>.qcow2 in your present working directory.

After you have created the OS image, assuming that you have installed QEMU, you can boot the AutoSD image in a virtual machine by using the automotive-image-runner utility and verify that the containerized application is included in the built OS image:

  1. Run the image in QEMU using automotive-image-runner:

    $ sudo automotive-image-runner container_remote.x86_64.qcow2
    

    If necessary, substitute the filename of your .qcow2 image file.

  2. After the image has booted in QEMU, log in with the user name root and the password password.

  3. Verify that your containerized application image is available:

    # podman image list
    

    Sample output:

    REPOSITORY           TAG         IMAGE ID      CREATED            SIZE
    localhost/cs10  latest      054a7b912609  About an hour ago  250 MB
    

When you build your OS image, OSBuild copies the application container image from the remote container image registry to your OS image. As defined in the build manifest file, the containerized application is available at localhost/cs10 and can be run by using Podman. However, you must first create container configuration files and configure OSBuild to copy these files to the /etc/containers/systemd directory in your OS image. For more information about these container configuration files, see Running containers from systemd.

Next steps

Additional resources

Embedding local containerized applications

You can embed containerized applications from local storage when you build an AutoSD operating system (OS) image. Doing so makes the containerized application available for use from within the AutoSD OS after the system boots. This method uses the containers-storage option in the build manifest so that OSBuild pulls containers from local container image storage at build time and includes them into the OS image.

Important

Although you can containerize applications locally and embed them when building an OS image, doing so is not the recommended method of building the OS image and is meant only for development or experimental purposes. If you want to include containerized applications in an OS image, pulling containers from a secure remote container image registry is the only reliable, reproducible, and recommended method for OS image builds.

Prerequisites

Sample procedure

This sample procedure explains how to create an automotive image builder manifest and build an AutoSD operating system image in the qcow2 format that you can boot in a QEMU virtual machine.

The resulting AutoSD OS image will include a containerized auto-apps application image pulled from local storage and installed to the /usr/share/containers/storage directory in the OS.

Note that you can customize the script and the manifest to pull your own containerized application images from local storage.

  1. Create a build manifest file named container_local.aib.yml:

    $ touch container_local.aib.yml
    
  2. Open the container_local.aib.yml file in a text editor, add the following YAML code, and save the file:

    Sample manifest for embedding local container images
    # hosted in the local container registry on the build machine
    
    name: container_local
    
    content:
      repos:
        - id: epel
          baseurl: https://dl.fedoraproject.org/pub/epel/9/Everything/$arch/
      rpms:
        - podman
        # For testing the image only:
        - openssh-server
        - openssh-clients
    
      container_images:
        - source: "localhost/auto-apps"
          tag: latest
          name: "localhost/auto-apps"
          containers-transport: containers-storage
    
      # Required for testing the image only:
      systemd:
        enabled_services:
          # Enable ssh daemon
          - sshd.service
    
    auth:
      # "password"
      root_password: $6$xoLqEUz0cGGJRx01$H3H/bFm0myJPULNMtbSsOFd/2BnHqHkMD92Sfxd.EKM9hXTWSmELG8cf205l6dktomuTcgKGGtGDgtvHVXSWU.
      # Required for testing the image only:
      sshd_config:
        PasswordAuthentication: true
        PermitRootLogin: true
    
  3. Export the value of your hardware architecture to a temporary variable:

    $ export arch=$(arch)
    
  4. Run the automotive-image-builder script to build an OS image that embeds the remote containerized application:

    $ sudo automotive-image-builder \
        --verbose \
        --include=/var/lib/containers/storage/ \
        build \
        --distro autosd9 \
        --target qemu \
        --mode image \
        --build-dir=_build \
        --export qcow2 \
        container_local.aib.yml \
        container_local.$arch.qcow2
    
  5. Verify that the script has created an AutoSD image file named container_local.<arch>.qcow2 in your present working directory.

After you have created the OS image, assuming that you have installed QEMU, you can boot the AutoSD image in a virtual machine by using the automotive-image-runner utility and verify that the containerized application is included in the built OS image:

  1. Run the image in QEMU using automotive-image-runner:

    $ sudo automotive-image-runner container_local.x86_64.qcow2
    

    If necessary, substitute the filename of your .qcow2 image file.

  2. After the image has booted in QEMU, log in with the user name root and the password password.

  3. Verify that your containerized application image is available:

    # podman image list
    

    Sample output:

    REPOSITORY           TAG         IMAGE ID      CREATED            SIZE
    localhost/auto-apps  latest      054a7b912609  About an hour ago  250 MB
    

When you build your OS image, OSBuild copies the auto-apps container image to your OS image. Your containerized auto-apps application is available at localhost/auto-apps. You must also create container configuration files and configure OSBuild to copy these files to the /etc/containers/systemd directory in your OS image. For more information about these container configuration files, see Running containers from systemd.

Next steps

Additional resources

Running containers from systemd

When you embed a container in an operating system (OS) image, you can start the container manually in the booted system with the podman run command. However, the container does not start automatically at boot time. To configure a container to start at boot time, you must create a systemd service that starts the container at the right time, in the right way.

Quadlet is a tool that optimally runs Podman containers under systemd. Rather than creating the systemd service manually, use Quadlet to automatically generate the corresponding systemd service unit file at boot time. In this example, create Quadlet files for the sample applications that are available in the AutoSD sample apps repository. If you want to use your own containerized software, see the Podman documentation for more information about creating your own Quadlet configuration files.

Prerequisites

Procedure

  1. Create Quadlet unit files for the radio-service and engine-service services in your sample application auto-apps:

    radio.container file
    [Unit]
    Description=Demo radio service container
    Requires=routingmanagerd.socket
    After=routingmanagerd.socket
    Wants=engine.service
    
    [Container]
    Image=localhost/auto-apps
    Exec=/usr/bin/radio-service
    Volume=/run/vsomeip:/run/vsomeip
    
    [Service]
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    
    engine.container file
    [Unit]
    Description=Demo engine service container
    Requires=routingmanagerd.socket
    After=routingmanagerd.socket
    
    [Container]
    Image=localhost/auto-apps
    Exec=/usr/bin/engine-service
    Volume=/run/vsomeip:/run/vsomeip
    
    [Service]
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    
  2. Create an automotive image builder manifest named quadlet_radio_engine.aib.yml that contains the following code, which copies the Quadlet unit files to the /etc/containers/systemd/ directory during the OS image build process:

    Manifest configuration to copy Quadlet unit files
    # Example manifest building an image with, pre-installed, a container image
    # hosted in a remote container registry
    
    name: quadlet_radio_engine
    
    content:
      repos:
        - id: copr-sample-apps
          baseurl: https://download.copr.fedorainfracloud.org/results/alexl/cs9-sample-images/centos-stream-9-$arch/
      rpms:
        - podman
        - containernetworking-plugins
        - vsomeip3-routingmanager
        - dlt-daemon
        # For testing the image only:
        - openssh-server
        - openssh-clients
    
      container_images:
        # Get the auto-apps container image from gitlab
        - source: registry.gitlab.com/centos/automotive/sample-images/demo/auto-apps
          tag: latest
          name: localhost/auto-apps
    
      add_files:
        - path: /etc/containers/systemd/radio.container
          source_path: ../radio.container
        - path: /etc/containers/systemd/engine.container
          source_path: ../engine.container
    
      # Required for testing the image only:
      systemd:
        enabled_services:
          # Enable ssh daemon
          - sshd.service
          # Enable the dlt daemon
          - dlt
    
    auth:
      # "password"
      root_password: $6$xoLqEUz0cGGJRx01$H3H/bFm0myJPULNMtbSsOFd/2BnHqHkMD92Sfxd.EKM9hXTWSmELG8cf205l6dktomuTcgKGGtGDgtvHVXSWU.
      # Required for testing the image only:
      sshd_config:
        PasswordAuthentication: true
        PermitRootLogin: true
    

    Note

    The path: option resolves a relative path. In this example, your Quadlet unit files are in the ../ directory.

  3. Run the automotive-image-builder tool to build an OS image:

    $ sudo automotive-image-builder \
        --verbose --container \
        --include=/var/lib/containers/storage/ \
        build \
        --distro autosd9 \
        --target qemu \
        --mode image \
        --build-dir=_build \
        --export qcow2 \
        quadlet_radio_engine.aib.yml \
        quadlet_radio_engine.$arch.qcow2
    
  4. Verify that the script has created an AutoSD image file named quadlet_radio_engine.<arch>.qcow2 in your present working directory.

After you have created the OS image, assuming that you have installed QEMU, you can boot the AutoSD image in a virtual machine by using the automotive-image-runner utility:

  1. Run the image in QEMU using the automotive-image-runner script:

    $ sudo automotive-image-runner quadlet_radio_engine.x86_64.qcow2
    

    If necessary, substitute the filename of your .qcow2 image file.

  2. After the image has booted in QEMU, log in with the user name root and the password password.

Additional resources


© Red Hat