Skip to content

Instantly share code, notes, and snippets.

@mkulke
Created May 11, 2026 12:57
Show Gist options
  • Select an option

  • Save mkulke/484858d6ce05bc7ac43d5e13a2c526aa to your computer and use it in GitHub Desktop.

Select an option

Save mkulke/484858d6ce05bc7ac43d5e13a2c526aa to your computer and use it in GitHub Desktop.
# syntax=docker/dockerfile:1.3-labs
FROM quay.io/centos/centos:stream9 AS payload-builder
RUN dnf -y update && dnf -y install \
mtools \
wget \
dosfstools
RUN wget https://cloud-images.ubuntu.com/minimal/releases/jammy/release/ubuntu-22.04-minimal-cloudimg-amd64.img -O /tmp/os-image.qcow2
RUN mkdir cidata
COPY <<EOF cidata/meta-data
instance-id: cloud
local-hostname: cloud
EOF
COPY <<-EOF cidata/network-config
version: 2
ethernets:
eth0:
match:
macaddress: 00:10:20:30:40:50
dhcp4: true
EOF
COPY <<-"EOF" cidata/user-data
#cloud-config
users:
- name: "cloud"
passwd: "$6$Nj5/QLVsGjcm87Qh$2m1i14vBh1RNHrXXwr4z6Tnn9yDBb4pbWCbvbfT2web8IKzozaT/gW6.1iKyo3GF2atlqyP5nUPquKFjNMNuV0"
sudo: "ALL=(ALL) NOPASSWD:ALL"
lock_passwd: false
ssh_pwauth: true
EOF
RUN mkdosfs -n CIDATA -C /tmp/cidata.img 8192
RUN mcopy -oi /tmp/cidata.img -s cidata/user-data ::
RUN mcopy -oi /tmp/cidata.img -s cidata/meta-data ::
RUN mcopy -oi /tmp/cidata.img -s cidata/network-config ::
FROM quay.io/centos/centos:stream9
RUN dnf -y update && \
dnf -y install \
qemu-kvm \
libvirt-daemon-driver-qemu \
libvirt-client \
passt && \
dnf clean all
RUN mkdir -p \
/var/run/libvirt/qemu \
/var/lib/libvirt/qemu \
/var/log/libvirt/qemu \
/var/run/qemu/logs
ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 /usr/local/bin/dumb-init
RUN chmod +x /usr/local/bin/dumb-init
COPY <<"EOF" /etc/libvirt/virtqemud.conf
auth_unix_rw = "none"
EOF
COPY <<"EOF" /etc/libvirt/qemu.conf
security_driver = "none"
user = "root"
group = "root"
dynamic_ownership = 0
remember_owner = 0
cgroup_controllers = []
EOF
COPY <<'EOF' /etc/libvirt/qemu/cloud-vm.xml
<domain type='qemu' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<name>cloud-vm</name>
<memory unit='MiB'>2048</memory>
<vcpu placement='static'>2</vcpu>
<os>
<type arch='x86_64' machine='q35'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<on_poweroff>destroy</on_poweroff>
<on_reboot>destroy</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/qemu/os-image.qcow2'/>
<target dev='vda' bus='virtio'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/qemu/cidata.img'/>
<target dev='vdb' bus='virtio'/>
</disk>
<interface type='user'>
<mac address='00:10:20:30:40:50'/>
<model type='virtio'/>
<backend type='passt'/>
<portForward proto='tcp'>
<range start='2222' to='22'/>
</portForward>
</interface>
<serial type='file'>
<source path='/var/run/qemu/logs/serial.log'/>
<target type='isa-serial' port='0'/>
</serial>
</devices>
<qemu:commandline>
<qemu:arg value='-accel'/>
<qemu:arg value='mshv'/>
</qemu:commandline>
</domain>
EOF
COPY <<"EOF" /usr/local/bin/entrypoint.sh
#!/bin/bash
set -euo pipefail
export LIBVIRT_DEFAULT_URI="qemu+unix:///system?socket=/run/libvirt/virtqemud-sock"
LOG_DIR=/var/run/qemu/logs
mkdir -p "$LOG_DIR"
: > "$LOG_DIR/serial.log"
/usr/sbin/virtlogd -d
/usr/sbin/virtqemud -d
for _ in $(seq 1 20); do
virsh list >/dev/null 2>&1 && break
sleep 0.5
done
virsh start cloud-vm
exec tail -F "$LOG_DIR/serial.log"
EOF
RUN chmod +x /usr/local/bin/entrypoint.sh
RUN mkdir -p /var/lib/qemu/
COPY --from=payload-builder /tmp/os-image.qcow2 /var/lib/qemu/
COPY --from=payload-builder /tmp/cidata.img /var/lib/qemu/
# $ sudo podman run --privileged --group-add keep-groups -v /dev/mshv:/dev/mshv -v $PWD/logs:/var/run/qemu/logs -p 2222:2222 -d ghcr.io/mkulke/libvirt:...
ENTRYPOINT ["/usr/local/bin/dumb-init", "--", "/usr/local/bin/entrypoint.sh"]
CMD []
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment