🐳
QEMUとのVirtfsを使ったファイル共有を実現するDockerfile
成果
VirtfsでQEMU上で動くカーネルとホストでファイル共有する最小に近い構成をdockerで再現可能な形で示した。
前提
-
docker
orpodman
が動く
手順
後に添付するファイルを同じディレクトリに配置して、以下を実行。
ls
# expect:> Dockerfile init linux-config.sh
docker image build --target output -t virtfs-sample .
docker container run --rm -it --device=/dev/kvm:/dev/kvm virtfs-sample /bin/bash
# 以下 docker container の中
mkdir /root/shared
touch /root/shared/hello-virtfs
qemu-system-x86_64 \
-enable-kvm \
-k ja \
-m 2048 \
-cpu host \
-smp 4 \
-net nic \
-device pci-testdev,membar=1M \
-kernel /out/bzImage \
-initrd /out/initrd.cpio.gz \
-append 'console=ttyS0 nokaslr' \
-virtfs local,path=/root/shared,mount_tag=hostshare,security_model=passthrough,id=shared0 \
-nographic
# 以下VM上のカーネル内
ls /mnt/host
# expect: hello-virtfs
ファイル
Dockerfile
FROM mirror.gcr.io/ubuntu:24.04 AS build_base
RUN \
rm -f /etc/apt/apt.conf.d/docker-clean \
&& apt-get update && apt-get install -y --no-install-recommends \
build-essential ncurses-dev flex bison bc libelf-dev libssl-dev \
wget cpio\
git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build libnfs-dev libiscsi-dev python3-pip python3-venv
# Linux Kernel
FROM build_base AS kernel_build
WORKDIR /src/kernel
ARG KERNEL_URL="https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.14.tar.xz"
ARG KERNEL_CONFIG_SH="/src/kernel/scripts/config.sh"
ARG KERNEL_GCC="gcc-10"
RUN wget ${KERNEL_URL} -O linux.tar.gz \
&& mkdir linux \
&& tar Jxfv linux.tar.gz -C linux --strip-components 1
COPY ./linux-config.sh ${KERNEL_CONFIG_SH}
RUN \
rm -f /etc/apt/apt.conf.d/docker-clean \
&& apt-get update && apt-get install -y --no-install-recommends \
${KERNEL_GCC}
RUN cd linux \
&& make defconfig \
&& chmod +x ${KERNEL_CONFIG_SH} \
&& ${KERNEL_CONFIG_SH} \
&& make olddefconfig \
&& make HOSTCC=${KERNEL_GCC} CC=${KERNEL_GCC} -j$(nproc) bzImage vmlinux
# Busybox + initrd
FROM build_base AS initrd
WORKDIR /src/initrd
RUN mkdir -p \
/src/initrd/rootfs/bin \
/src/initrd/rootfs/sbin \
/src/initrd/rootfs/etc \
/src/initrd/rootfs/proc \
/src/initrd/rootfs/sys \
/src/initrd/rootfs/new_root \
/src/initrd/rootfs/dev
ARG BUSYBOX_URL="https://busybox.net/downloads/busybox-1.35.0.tar.bz2"
ARG BUSYBOX_GCC="gcc-10"
RUN \
rm -f /etc/apt/apt.conf.d/docker-clean \
&& apt-get update && apt-get install -y --no-install-recommends \
${BUSYBOX_GCC}
RUN wget ${BUSYBOX_URL} -O busybox.tar.bz2 \
&& mkdir busybox \
&& tar -jxvf busybox.tar.bz2 -C busybox --strip-components 1 \
&& cd busybox \
&& make defconfig \
&& sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config \
# Couldn't build `tc` (https://lists.busybox.net/pipermail/busybox-cvs/2024-January/041752.html)
&& sed -i 's/CONFIG_TC=y/# CONFIG_TC is not set/' .config \
&& make HOSTCC=${BUSYBOX_GCC} CC=${BUSYBOX_GCC} -j$(nproc) \
&& make CONFIG_PREFIX=/src/initrd/rootfs install
COPY ./init /src/initrd/rootfs/init
RUN chmod +x /src/initrd/rootfs/init \
&& cd /src/initrd/rootfs \
&& find . | cpio -o -H newc | gzip > /src/initrd/initrd.cpio.gz
# QEMU with custom device
FROM build_base AS qemu_build
WORKDIR /src/qemu
ARG QEMU_GIT_REMOTE_URL="https://gitlab.com/qemu-project/qemu.git"
RUN git clone ${QEMU_GIT_REMOTE_URL} \
&& cd qemu \
&& ./configure --target-list=x86_64-softmmu --enable-debug \
&& make -j$(nproc) \
&& make DESTDIR=/src/qemu install
FROM mirror.gcr.io/ubuntu:24.04 AS output
COPY /src/kernel/linux/arch/x86/boot/bzImage /out/bzImage
COPY /src/kernel/linux/vmlinux /out/vmlinux
COPY /src/initrd/initrd.cpio.gz /out/initrd.cpio.gz
COPY /src/qemu/usr/ /usr/
RUN \
rm -f /etc/apt/apt.conf.d/docker-clean \
&& apt-get update && apt-get install -y --no-install-recommends \
gdb libnfs-dev libiscsi-dev libfdt-dev libpixman-1-dev
init
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
echo "[init] Try to mount virtfs ..."
mkdir -p /mnt/host
mount -t 9p -o trans=virtio hostshare /mnt/host
echo "[init] Contents of '/mnt/host'"
ls /mnt/host
echo "[init] Enter to shell"
exec setsid cttyhack sh
linux-config.sh
# Debug
./scripts/config --enable DEBUG_INFO
./scripts/config --enable DEBUG_KERNEL
# Virtfs
./scripts/config --enable CONFIG_NET_9P
./scripts/config --enable CONFIG_NET_9P_VIRTIO
./scripts/config --enable CONFIG_NET_9P_DEBUG
./scripts/config --enable CONFIG_9P_FS
./scripts/config --enable CONFIG_9P_FS_POSIX_ACL
./scripts/config --enable CONFIG_PCI
./scripts/config --enable CONFIG_VIRTIO_PCI
Discussion