Bootstrapping Alpine Linux QCow2 image
Introduction
Alpine Linux is a minimal distro with package manager (APK) that is based on busybox and musl library. Like the CirrOS, it's very lightweight, but unlike it, it's full featured.
In case you don't know me, my Linux distro of choice is Fedora/CentOS, in this post I'm going to bootstrap a QCow2 cloud image of Alpine Linux on my distro of choice.
Using docker to bootstrap a working chroot
Type
mkdir alpine35-root
docker run --rm -ti -v $PWD/alpine35-root:/data alpine:3.5 apk --arch x86_64 -X http://nl.alpinelinux.org/alpine/v3.5/main/ -U --allow-untrusted --root /data --initdb add alpine-base
and you should get a line like this
OK: 6 MiB in 16 packages
so now we have a working alpine chroot in the directory alpine35-root
Creating Bootable QCoW2 Image
Because I don't want to format my hard disk by mistake and because I know Murphy's law, I'll take those 6MB as tarball and continue on a VM.
dd if=/dev/zero of=alpine.raw bs=1M seek=511 count=1
dd if=/dev/zero of=alpine.raw bs=512 count=2049 conv=notrunc
echo "2048,,83,*" | sfdisk ./alpine.raw
losetup -fP alpine.raw
export DEV=`losetup | grep alpine.raw | awk '{print $1}'`
export DEV1="${DEV}p1"
mkfs.xfs -L rootfs "$DEV1"
mkdir alpine35-root/img-root
mount "$DEV1" alpine35-root/img-root
chroot alpine35-root /bin/sh
NOTE you can use losetup -f alpine.raw -o $((2048 * 512))
now inside that chroot
export PATH=/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
echo "nameserver 8.8.8.8" > /etc/resolv.conf
apk --arch x86_64 -X http://nl.alpinelinux.org/alpine/edge/main/ -X http://nl.alpinelinux.org/alpine/edge/community/ -X http://nl.alpinelinux.org/alpine/edge/testing/ -U --allow-untrusted --root /img-root --initdb add alpine-base linux-virtgrsec grub grub-bios openrc
the final result should be something like
OK: 102 MiB in 27 packages
just exit the chroot, and
umount "$DEV1"
Installing grub
mkdir img-root
mount "$DEV1" img-root
mkdir -p img-root/{dev,proc,sys}
mount -o bind /dev img-root/dev
echo "LABEL=rootfs / auto defaults 1 1" >> img-root/etc/fstab
mkdir -p img-root/boot/grub/ || :
echo -e "(hd0) /dev/loop0" > img-root/boot/grub/device.map
inside chroot make sure to create a working initrd using some custom ramfs-init.sh
export PATH=/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
mount -t proc none /proc/
mount -t sysfs none /sys
export KERNEL=`find /lib/modules/* -maxdepth 0 -type d | cut -d '/' -f 4`
mkinitfs -F "ata base cdrom ext2 ext3 ext4 keymap kms mmc raid scsi usb virtio xfs" -i ramfs-init.sh $KERNEL
the method below did not work (from inside target chroot, maybe I should have used the other base chroot to do grub-install)
grub-install --boot-directory=/boot/ $DEV
so I had to use fedora's grub2-install, exit the chroot and type
grub-install --boot-directory=img-root/boot/ $DEV
Place a simple grub config file into img-root/boot/grub/grub.cfg or img-root/boot/grub2/grub.cfg ( in case you used fedora's grub2), the file should have 4 lines
menuentry 'alpine' {
linux (hd0,msdos1)/boot/vmlinuz-virtgrsec
initrd (hd0,msfos1)/boot/initramfs-virtgrsec
}
let's do some clean up by typing
umount img-root/proc
umount img-root/sys
umount img-root/dev
umount img-root
mount | grep img-root
losetup -D
losetup
NOTE: alpine uses /usr/share/mkinitfs/initramfs-init we have just removed unused parts
Converting it to QCow2
qemu-img convert -c -O qcow2 -f raw alpine.raw alpine.qcow2
or even better (not much better because it's already sparse)
virt-sparsify --compress --convert qcow2 --format raw alpine.raw alpine.qcow2
the qcow2 was about 40MB
Comments
Post a Comment