1

Description

As a side project, I am trying to use Hashicorp Packer along with Docker to create Bootable disk Images from Docker Containers.

Hashicorp Packer generally takes the responsibility of bringing the docker containers up and execute tasks within them and then create filesystem tarballs or use containers to create image files etc.

How it works

  1. I use an ubuntu:focal docker container

  2. use this docker container and install a Kernel / Systemd On it:

     apt-get update && apt-get install -y --no-install-recommends linux-image-virtual systemd-sysv
    
  3. Create a tarball of the container which now contains the kernel, initrd and system from step 2

  4. unpack the tarball on the host machine to be able to use it when creating an image file

  5. Spin up another ubuntu container with privileges and mount the working directory into it to create the bootable image file.

At this point I am relying on a bash script below to create an image for me:

set -e
echo "[Install APT dependencies]"
DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y extlinux fdisk qemu-utils

echo "[Create disk image of 1GB]"
dd if=/dev/zero of=/os/${DISTR}.img bs=$(expr 1024 \* 1024 \* 1024) count=1

blue "[Make partition]"
sfdisk /os/${DISTR}.img < /os/config/partition.txt

echo "\n[Format partition with ext4]"
losetup -D
LOOPDEVICE=$(losetup -f)
echo -e "\n[Using ${LOOPDEVICE} loop device]"
losetup -o $(expr 512 \* 2048) ${LOOPDEVICE} /os/${DISTR}.img
mkfs.ext4 ${LOOPDEVICE}

echo "[Copy ${DISTR} directory structure to partition]"
mkdir -p /os/mnt
mount -t auto ${LOOPDEVICE} /os/mnt/
cp -R /os/${DISTR}.dir/. /os/mnt/


echo "[Setup extlinux]"
extlinux --install /os/mnt/boot/
cp /os/config/syslinux.cfg /os/mnt/boot/syslinux.cfg

echo "[Unmount]"
umount /os/mnt
losetup -D

echo_blue "[Write syslinux MBR]"
dd if=/usr/lib/syslinux/mbr/mbr.bin of=/os/${DISTR}.img bs=440 count=1 conv=notrunc

The DISTR in the above script is ubuntu and the ubuntu.dir is the unpacked tarball ball which is mounted into the container to be able to copy it to the mounted partition.

Progress

Currently I have been successful in creating such images for ubuntu. The repository created can be found here

However upon trying to boot the image using qemu-system-x86_64:

sudo qemu-system-x86_64 -drive file=ubuntu.img,index=0,media=disk,format=raw 

I get the following error: Initrd error 1

The respective syslinux.cfg for the bootloader is:

DEFAULT linux
  SAY Now booting the kernel from SYSLINUX...
 LABEL linux
  KERNEL /boot/vmlinuz
  INITRD /boot/initrd.img-5.4.0-125-generic
  APPEND ro root=/dev/sda1

Additional Changes

I tried updating the syslinux.cfg to

DEFAULT linux
  SAY Now booting the kernel from SYSLINUX...
 LABEL linux
  KERNEL /boot/vmlinuz
  APPEND ro root=/dev/sda1 initrd=/boot/initrd.img

however I get the same error, albeit /boot/initrd.img is not found is the error message.

What am I currently missing from myside to make the initrd.img discoverable for the bootloader.

I have tried using cp -dR /os/ubuntu.dir/. /os/mnt in the bash script to make sure symbolic links are preserved while copying.

I have also made sure to see if the symlink initrd.img file exists in the mounted partition /os/mnt/boot which it exists and so does the source of the symlink file e.g. readlink -f /os/mnt/boot/initrd.img

Sources

iximiuz blogpost on docker-to-bootable devices PockerISO

1 Answer 1

1

I found out the solution to the problem. It was the fact that although I was installing the linux kernel via

apt-get install -y --no-install-recommends linux-image-virtual

It was unable to generate the initrd which usually happens when I let the complete recommended packages get installed.

I was able to solve this issue simply by

apt-get install -y linux-image-virtual

and I am able to create Bootable Images for Ubuntu as well as Debian

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .