Creating bootable images

This document describes the requirements to create standard container images that can be used for cOS deployments

You can find the examples below in the examples folder.

From standard images

Besides using the cos-toolkit toolchain, it’s possible to create standard container images which are consumable by the vanilla cOS images (ISO, Cloud Images, etc.) during the upgrade and deploy phase.

An example of a Dockerfile image can be:

ARG LUET_VERSION=0.20.6
FROM quay.io/luet/base:$LUET_VERSION AS luet

FROM opensuse/leap:15.3

ENV COSIGN_EXPERIMENTAL=1
ENV COSIGN_REPOSITORY=raccos/releases-green

ARG ARCH=amd64
ENV ARCH=${ARCH}
RUN zypper in -y \
    bash-completion \
    conntrack-tools \
    coreutils \
    curl \
    device-mapper \
    dosfstools \
    dracut \
    e2fsprogs \
    findutils \
    gawk \
    gptfdisk \
    grub2-i386-pc \
    grub2-x86_64-efi \
    haveged \
    iproute2 \
    iptables \
    iputils \
    issue-generator \
    jq \
    kernel-default \
    kernel-firmware-bnx2 \
    kernel-firmware-i915 \
    kernel-firmware-intel \
    kernel-firmware-iwlwifi \
    kernel-firmware-mellanox \
    kernel-firmware-network \
    kernel-firmware-platform \
    kernel-firmware-realtek \
    less \
    lsscsi \
    lvm2 \
    mdadm \
    multipath-tools \
    nano \
    NetworkManager\
    nfs-utils \
    open-iscsi \
    open-vm-tools \
    parted \
    pigz \
    policycoreutils \
    procps \
    python-azure-agent \
    qemu-guest-agent \
    rng-tools \
    rsync \
    squashfs \
    strace \
    systemd \
    systemd-sysvinit \
    tar \
    timezone \
    vim \
    which

RUN zypper cc

# Configure NetworkManager as default network management service
RUN zypper remove -y wicked
RUN systemctl disable wicked \
    && systemctl enable NetworkManager

# Copy the luet config file pointing to the upgrade repository
COPY conf/luet.yaml /etc/luet/luet.yaml

# Copy luet from the official images
COPY --from=luet /usr/bin/luet /usr/bin/luet

RUN luet install -y meta/cos-verify

RUN luet install --plugin luet-cosign -y meta/cos-minimal \
    utils/k9s \
    utils/nerdctl

COPY files/ /
RUN mkinitrd
Complete source code: https://github.com/rancher-sandbox/cos-toolkit/blob/master/examples/standard/Dockerfile

While the config file:

logging:
  color: false
  enable_emoji: false
general:
   debug: false
   spinner_charset: 9
repositories:
- name: "cos"
  description: "cOS official"
  type: "docker"
  enable: true
  cached: true
  priority: 1
  verify: false
  urls:
  - "quay.io/costoolkit/releases-green"
Complete source code: https://github.com/rancher-sandbox/cos-toolkit/blob/master/examples/standard/conf/luet.yaml

We can just run docker to build the image with

docker build -t $IMAGE .

The important piece is that an image needs to ship at least:

toolchain/yip
utils/installer
system/cos-setup
system/immutable-rootfs
system/grub2-config

from the toolchain. If you want to customize further the container further add more step afterwards luet install see the customizing section.

Generating from CI image

Derivatives can be stacked on top of another, so it is possible to reuse directly also the vanilla cOS images:

# Pick one version from https://quay.io/repository/costoolkit/releases-green?tab=tags
FROM quay.io/costoolkit/releases-green:cos-system-0.5.8-4

COPY files/ /
Complete source code: https://github.com/rancher-sandbox/cos-toolkit/blob/master/examples/cos-official/Dockerfile

The images contains already the toolkit, so they can be used as-is and apply further customization on top.

From scratch

The luet image quay.io/luet/base contains just luet, and can be used to boostrap the base system from scratch:

conf/luet.yaml:

logging:
  color: false
  enable_emoji: false
general:
   debug: false
   spinner_charset: 9
repositories:
- name: "cos"
  description: "cOS official"
  type: "docker"
  enable: true
  cached: true
  priority: 1
  verify: false
  urls:
  - "quay.io/costoolkit/releases-green"
Complete source code: https://github.com/rancher-sandbox/cos-toolkit/blob/master/examples/scratch/conf/luet.yaml

Dockerfile:

ARG LUET_VERSION=0.20.6

FROM quay.io/luet/base:$LUET_VERSION AS luet

FROM opensuse/leap:15.3 AS ca

FROM scratch

# Copy luet from the official images
COPY --from=luet /usr/bin/luet /usr/bin/luet
COPY --from=ca /etc/ssl/certs/. /etc/ssl/certs/

# Copy the luet config file pointing to the cOS repository
ADD conf/luet.yaml /etc/luet/luet.yaml
ENV USER=root
ENV LUET_NOLOCK=true
SHELL ["/usr/bin/luet", "install", "-y", "-d"]

RUN system/cos-container

SHELL ["/bin/sh", "-c"]
RUN rm -rf /var/cache/luet/packages/ /var/cache/luet/repos/

ENV TMPDIR=/tmp
ENTRYPOINT ["/bin/sh"]
Complete source code: https://github.com/rancher-sandbox/cos-toolkit/blob/master/examples/scratch/Dockerfile

Customizations

All the method above imply that the image generated will be the booting one, there are however several configuration entrypoint that you should keep in mind while building the image:

  • Everything under /system/oem will be loaded during the various stage (boot, network, initramfs). You can check here for the cOS defaults. See 00_rootfs.yaml to customize the booting layout.
  • /etc/cos/bootargs.cfg contains the booting options required to boot the image with GRUB
  • /etc/cos-upgrade-image contains the default upgrade configuration for recovery and the booting system image

Configuration file

The example configuration file shows how to enable the cos-toolkit repository:

logging:
  color: false
  enable_emoji: false
general:
   debug: false
   spinner_charset: 9
repositories:
- name: "cos"
  description: "cOS official"
  type: "docker"
  enable: true
  cached: true
  priority: 1
  verify: false
  urls:
  - "quay.io/costoolkit/releases-green"
Complete source code: https://github.com/rancher-sandbox/cos-toolkit/blob/master/examples/standard/conf/luet.yaml

Repositories have the following fields, notably:

  • name: Repository name
  • enable: Enable/disables the repository
  • arch: (optional) Denotes the arch repository. If present, it will enable the repository automatically if the corresponding arch is matching with the host running luet. enable: true would override this behavior
  • reference: (optional) A reference to a repository index file to use to retrieve the repository metadata instead of latest. This can be used to point to a different or an older repository index to act as a “wayback machine”. The client will consume the repository state from that snapshot instead of latest.

Last modified May 6, 2022 : Skip generating docs (d29a239)