bootc-docs/building/base-images.md
robojerk 72155be8de CRITICAL: Correct dangerous claims about bootc production readiness
EXPERIMENTAL WARNINGS:
- Add prominent warnings that bootc on Debian is HIGHLY EXPERIMENTAL
- Clarify that NO reproducible bootc images exist yet
- Warn that everything is still experimental and not production-ready
- Add DO NOT use in production warnings throughout

DEBIAN VERSION CORRECTIONS:
- Use Debian Sid (unstable) for base image building (like Fedora rawhide)
- Correct dangerous claims about 'tested' configurations
- Mark all configurations as experimental, not tested
- Remove false claims about production readiness

SAFETY IMPROVEMENTS:
- Add experimental warnings to all base image documentation
- Clarify that bootc is not stable on Debian yet
- Emphasize testing-only use on virtual machines
- Remove misleading production recommendations

This corrects dangerous misinformation that could lead to
data loss and system instability in production environments.
2025-09-15 14:24:27 -07:00

11 KiB

Building Base bootc Images

⚠️ EXPERIMENTAL WARNING ⚠️

bootc on Debian is HIGHLY EXPERIMENTAL and NOT production-ready!

  • No reproducible bootc images exist yet - Everything is experimental
  • Use only for testing on virtual machines or test hardware
  • Expect failures - bootc is not stable on Debian
  • DO NOT use in production - Data loss and system instability possible

This document provides detailed instructions for creating base bootc images using two different approaches:

  1. Method 1: Building from an existing OCI image
  2. Method 2: Building from scratch using debootstrap/mmdebstrap

Important Note

bootc does not create base images - it only deploys and manages them. Base image creation requires separate tools and processes as described below.

Method 1: Building from Existing OCI Image

This method takes an existing Debian OCI image and converts it into a bootc-compatible base image.

Prerequisites

# Install required tools
sudo apt update
sudo apt install -y podman buildah skopeo

# Install bootc for validation
git clone https://github.com/containers/bootc.git
cd bootc
make
sudo make install

Step 1: Create Containerfile

Create a Containerfile.base:

# Containerfile.base - Convert existing Debian image to bootc base
FROM debian:sid-slim

# Install essential packages for bootc
RUN apt update && apt install -y \
    systemd \
    systemd-sysusers \
    systemd-tmpfiles \
    kernel \
    initramfs-tools \
    grub2 \
    grub2-common \
    efibootmgr \
    ostree \
    && apt clean

# Create essential directories
RUN mkdir -p /usr/lib/systemd/system \
    /usr/lib/systemd/user \
    /etc/systemd/system \
    /etc/systemd/user \
    /var/lib/systemd \
    /run/systemd

# Configure systemd as init
RUN ln -sf /lib/systemd/systemd /sbin/init

# Set up basic systemd configuration
RUN systemctl set-default multi-user.target

# Create essential systemd services
RUN systemctl enable systemd-resolved.service \
    systemd-networkd.service \
    systemd-timesyncd.service

# Configure basic networking
RUN echo -e "[Match]\nName=*\n\n[Network]\nDHCP=yes" > /etc/systemd/network/80-dhcp.network

# Set up basic users and groups
RUN systemd-sysusers --root=/ --create

# Configure tmpfiles
RUN systemd-tmpfiles --create --root=/

# Install bootc (for validation)
COPY --from=quay.io/containers/bootc:latest /usr/bin/bootc /usr/bin/bootc

# Validate the image
RUN bootc container lint

# Required bootc labels
LABEL containers.bootc 1
LABEL ostree.bootable 1

# Set default command
CMD ["/lib/systemd/systemd"]

Step 2: Build the Base Image

#!/bin/bash
# build-base-from-existing.sh

set -euo pipefail

IMAGE_NAME="debian-bootc-base"
TAG="${1:-latest}"

echo "🏗️  Building Debian bootc Base Image from Existing OCI"
echo "Image: ${IMAGE_NAME}:${TAG}"

# Build the base image
echo "📦 Building container image..."
podman build -f Containerfile.base -t "${IMAGE_NAME}:${TAG}" .

echo "✅ Base image built successfully!"
echo "Image: ${IMAGE_NAME}:${TAG}"

# Show image info
echo ""
echo "📊 Image Information:"
podman images "${IMAGE_NAME}:${TAG}"

echo ""
echo "🚀 Ready to build application layers!"
echo "Example: podman build -f examples/nginx/Containerfile -t ${IMAGE_NAME}:nginx"

Step 3: Test the Base Image

# Test the base image
podman run --rm -it debian-bootc-base:latest /bin/bash

# Validate with bootc
bootc container lint debian-bootc-base:latest

Method 2: Building from Scratch with debootstrap/mmdebstrap

This method creates a completely custom Debian base image from scratch.

Prerequisites

# Install required tools
sudo apt update
sudo apt install -y \
    debootstrap \
    mmdebstrap \
    podman \
    buildah \
    skopeo \
    qemu-user-static

# Install bootc for validation
git clone https://github.com/containers/bootc.git
cd bootc
make
sudo make install

Step 1: Create Root Filesystem

Create a script to build the root filesystem:

#!/bin/bash
# build-rootfs.sh - Build Debian rootfs from scratch

set -euo pipefail

ROOTFS_DIR="rootfs"
DEBIAN_RELEASE="bookworm"
ARCH="amd64"

echo "🏗️  Building Debian Root Filesystem from Scratch"
echo "Release: ${DEBIAN_RELEASE}"
echo "Architecture: ${ARCH}"
echo "Rootfs: ${ROOTFS_DIR}/"

# Clean up previous build
if [ -d "${ROOTFS_DIR}" ]; then
    echo "🧹 Cleaning up previous build..."
    sudo rm -rf "${ROOTFS_DIR}"
fi

# Create rootfs directory
mkdir -p "${ROOTFS_DIR}"

# Build rootfs with mmdebstrap (faster and more reliable)
echo "📦 Building rootfs with mmdebstrap..."
sudo mmdebstrap \
    --arch="${ARCH}" \
    --variant=minbase \
    --include=systemd,systemd-sysusers,systemd-tmpfiles,kernel,initramfs-tools,grub2,grub2-common,efibootmgr,ostree \
    "${DEBIAN_RELEASE}" \
    "${ROOTFS_DIR}" \
    http://deb.debian.org/debian

echo "✅ Rootfs built successfully!"

# Set up basic systemd configuration
echo "⚙️  Configuring systemd..."
sudo chroot "${ROOTFS_DIR}" systemctl set-default multi-user.target

# Create essential systemd services
sudo chroot "${ROOTFS_DIR}" systemctl enable systemd-resolved.service
sudo chroot "${ROOTFS_DIR}" systemctl enable systemd-networkd.service
sudo chroot "${ROOTFS_DIR}" systemctl enable systemd-timesyncd.service

# Configure basic networking
sudo tee "${ROOTFS_DIR}/etc/systemd/network/80-dhcp.network" > /dev/null <<EOF
[Match]
Name=*

[Network]
DHCP=yes
EOF

# Set up users and groups
sudo chroot "${ROOTFS_DIR}" systemd-sysusers --create

# Configure tmpfiles
sudo chroot "${ROOTFS_DIR}" systemd-tmpfiles --create

# Create essential directories
sudo mkdir -p "${ROOTFS_DIR}/usr/lib/systemd/system"
sudo mkdir -p "${ROOTFS_DIR}/usr/lib/systemd/user"
sudo mkdir -p "${ROOTFS_DIR}/etc/systemd/system"
sudo mkdir -p "${ROOTFS_DIR}/etc/systemd/user"
sudo mkdir -p "${ROOTFS_DIR}/var/lib/systemd"
sudo mkdir -p "${ROOTFS_DIR}/run/systemd"

# Configure systemd as init
sudo ln -sf /lib/systemd/systemd "${ROOTFS_DIR}/sbin/init"

# Set proper permissions
sudo chown -R root:root "${ROOTFS_DIR}"
sudo chmod 755 "${ROOTFS_DIR}"

echo "✅ Rootfs configuration complete!"
echo "Rootfs: ${ROOTFS_DIR}/"

Step 2: Create Containerfile for Scratch Build

Create a Containerfile.scratch:

# Containerfile.scratch - Build bootc image from scratch rootfs
FROM scratch

# Copy the entire rootfs
COPY rootfs/ /

# Install bootc (copy from existing image)
COPY --from=quay.io/containers/bootc:latest /usr/bin/bootc /usr/bin/bootc

# Validate the image
RUN bootc container lint

# Required bootc labels
LABEL containers.bootc 1
LABEL ostree.bootable 1

# Set default command
CMD ["/lib/systemd/systemd"]

Step 3: Build Script

Create the main build script:

#!/bin/bash
# build-scratch-bootc.sh - Complete build script for debian-scratch-bootc

set -euo pipefail

# Configuration
IMAGE_NAME="debian-scratch-bootc"
TAG="${1:-latest}"
ROOTFS_DIR="rootfs"

echo "🏗️  Building Debian Scratch Bootc Base Image"
echo "Image: ${IMAGE_NAME}:${TAG}"
echo "Rootfs: ${ROOTFS_DIR}/"

# Check if rootfs exists, build if not
if [ ! -d "${ROOTFS_DIR}" ]; then
    echo "📦 Building rootfs..."
    ./build-rootfs.sh
fi

# Build the base image
echo "📦 Building container image..."
podman build -f Containerfile.scratch -t "${IMAGE_NAME}:${TAG}" .

echo "✅ Base image built successfully!"
echo "Image: ${IMAGE_NAME}:${TAG}"

# Show image info
echo ""
echo "📊 Image Information:"
podman images "${IMAGE_NAME}:${TAG}"

echo ""
echo "🚀 Ready to build application layers!"
echo "Example: podman build -f examples/nginx/Containerfile -t ${IMAGE_NAME}:nginx"

Step 4: Create Example Application Layer

Create an example showing how to build on top of the base image:

# examples/nginx/Containerfile
FROM debian-scratch-bootc:latest

# Install nginx
RUN apt update && apt install -y nginx && apt clean

# Configure nginx
RUN echo "server { listen 80; location / { return 200 'Hello from bootc!'; } }" > /etc/nginx/sites-available/default
RUN ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/

# Enable nginx service
RUN systemctl enable nginx.service

# Validate the image
RUN bootc container lint

# Required bootc labels
LABEL containers.bootc 1
LABEL ostree.bootable 1

# Set default command
CMD ["/lib/systemd/systemd"]

Complete Project Structure

debian-bootc-base/
├── build-rootfs.sh              # Rootfs build script
├── build-scratch-bootc.sh       # Main build script
├── Containerfile.base           # From existing OCI image
├── Containerfile.scratch        # From scratch build
├── rootfs/                      # Generated rootfs (Method 2)
├── examples/
│   ├── nginx/
│   │   └── Containerfile        # Example nginx layer
│   └── apache/
│       └── Containerfile        # Example apache layer
└── README.md

Usage Examples

Method 1: From Existing Image

# Build base image from existing Debian
./build-base-from-existing.sh

# Build application layer
podman build -f examples/nginx/Containerfile -t debian-bootc-base:nginx .

Method 2: From Scratch

# Build rootfs and base image
./build-scratch-bootc.sh

# Build application layer
podman build -f examples/nginx/Containerfile -t debian-scratch-bootc:nginx .

Validation and Testing

Validate Base Image

# Validate with bootc
bootc container lint debian-bootc-base:latest
bootc container lint debian-scratch-bootc:latest

Test Base Image

# Test the base image
podman run --rm -it debian-bootc-base:latest /bin/bash
podman run --rm -it debian-scratch-bootc:latest /bin/bash

Deploy with bootc

# Install to filesystem
bootc install to-filesystem debian-bootc-base:latest

# Check status
bootc status

Troubleshooting

Common Issues

  1. Permission Errors: Ensure scripts are executable

    chmod +x build-*.sh
    
  2. Rootfs Build Fails: Check internet connection and mirrors

    # Test mirror connectivity
    curl -I http://deb.debian.org/debian/
    
  3. bootc Validation Fails: Check required labels and systemd configuration

    # Check labels
    podman inspect debian-bootc-base:latest | grep -A 10 Labels
    
    # Check systemd
    podman run --rm debian-bootc-base:latest systemctl --version
    
  4. Image Too Large: Optimize by removing unnecessary packages

    # Clean up in rootfs
    sudo chroot rootfs apt autoremove --purge -y
    sudo chroot rootfs apt clean
    

Advanced Configuration

Custom Kernel

# Install specific kernel version
sudo chroot rootfs apt install -y linux-image-6.1.0-10-amd64

Custom Systemd Services

# Add custom service
sudo tee rootfs/etc/systemd/system/myapp.service > /dev/null <<EOF
[Unit]
Description=My Application
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/myapp
Restart=always

[Install]
WantedBy=multi-user.target
EOF

sudo chroot rootfs systemctl enable myapp.service

Security Hardening

# Install security packages
sudo chroot rootfs apt install -y \
    apparmor \
    auditd \
    ufw \
    fail2ban

# Configure AppArmor
sudo chroot rootfs systemctl enable apparmor.service

This comprehensive guide provides everything needed to create base bootc images using both methods, with practical examples and troubleshooting tips.