From d497d705c7ed63b4abb8804959bc1518db73e33a Mon Sep 17 00:00:00 2001 From: Nate Choe Date: Mon, 20 Nov 2023 04:00:25 -0600 Subject: [PATCH] Add VNC support (#185) * VNC --- Dockerfile | 8 +++++++- docker-compose.yml | 3 +++ readme.md | 11 +++++++++++ src/display.sh | 15 +++++++++++++++ src/entry.sh | 6 ++++-- src/network.sh | 10 +++++++++- 6 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 src/display.sh diff --git a/Dockerfile b/Dockerfile index 476a64b0..96895baa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,12 +18,18 @@ RUN apt-get update && apt-get -y upgrade && \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -COPY src/*.sh /run/ +# Using a wildcard causes caching problems on some systems +COPY src/disk.sh /run/ +COPY src/display.sh /run/ +COPY src/entry.sh /run/ +COPY src/install.sh /run/ +COPY src/network.sh /run/ RUN chmod +x /run/*.sh VOLUME /storage EXPOSE 22 +EXPOSE 5900 ENV CPU_CORES "1" ENV DISK_SIZE "16G" diff --git a/docker-compose.yml b/docker-compose.yml index 5cbf2494..3fa57b37 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,8 @@ services: RAM_SIZE: "512M" DISK_SIZE: "16G" BOOT: "https://dl-cdn.alpinelinux.org/alpine/v3.18/releases/x86_64/alpine-standard-3.18.2-x86_64.iso" + DISPLAY: "vnc" + CONTROL_PORTS: "5900" devices: - /dev/kvm - /dev/vhost-net @@ -17,5 +19,6 @@ services: - NET_ADMIN ports: - 22:22 + - 5900:5900 restart: on-failure stop_grace_period: 1m diff --git a/readme.md b/readme.md index 4fb00e02..6da3ff9f 100644 --- a/readme.md +++ b/readme.md @@ -187,6 +187,17 @@ docker run -it --rm -e "BOOT=http://www.example.com/image.iso" --device=/dev/kvm Please note that even if you don't need DHCP, it's still recommended to enable this feature as it prevents NAT issues and increases performance by using a `macvtap` interface. + * ### How can I connect with VNC? + + To enable VNC, add the following lines to your compose file: + + ```yaml + ports: + "5900:5900" + environment: + DISPLAY: "vnc" + ``` + [build_url]: https://github.com/qemu-tools/qemu-docker/ [hub_url]: https://hub.docker.com/r/qemux/qemu-docker/ [tag_url]: https://hub.docker.com/r/qemux/qemu-docker/tags diff --git a/src/display.sh b/src/display.sh new file mode 100644 index 00000000..3e6f7586 --- /dev/null +++ b/src/display.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# Docker environment variables + +: ${DISPLAY:='none'} # Display type + +case "$DISPLAY" in + vnc) + DISPLAY_OPTS="-nographic -vga std -vnc :0" + ;; + *) + DISPLAY_OPTS="-nographic -display none" + ;; +esac diff --git a/src/entry.sh b/src/entry.sh index 18531057..2ba5d3e9 100755 --- a/src/entry.sh +++ b/src/entry.sh @@ -34,6 +34,7 @@ cd /run . install.sh # Get bootdisk . disk.sh # Initialize disks . network.sh # Initialize network +. display.sh # Initialize display KVM_ERR="" KVM_OPTS="" @@ -55,19 +56,20 @@ else KVM_OPTS=",accel=kvm -enable-kvm -cpu host" fi -DEF_OPTS="-nographic -nodefaults -display none" +DEF_OPTS="-nodefaults" RAM_OPTS=$(echo "-m ${RAM_SIZE}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g') CPU_OPTS="-smp ${CPU_CORES},sockets=1,dies=1,cores=${CPU_CORES},threads=1" MAC_OPTS="-machine type=q35,usb=off,dump-guest-core=off,hpet=off${KVM_OPTS}" SERIAL_OPTS="-serial mon:stdio -device virtio-serial-pci,id=virtio-serial0,bus=pcie.0,addr=0x3" EXTRA_OPTS="-device virtio-balloon-pci,id=balloon0 -object rng-random,id=rng0,filename=/dev/urandom -device virtio-rng-pci,rng=rng0" -ARGS="${DEF_OPTS} ${CPU_OPTS} ${RAM_OPTS} ${MAC_OPTS} ${SERIAL_OPTS} ${NET_OPTS} ${DISK_OPTS} ${EXTRA_OPTS} ${ARGUMENTS}" +ARGS="${DEF_OPTS} ${CPU_OPTS} ${RAM_OPTS} ${MAC_OPTS} ${SERIAL_OPTS} ${NET_OPTS} ${DISK_OPTS} ${DISPLAY_OPTS} ${EXTRA_OPTS} ${ARGUMENTS}" ARGS=$(echo "$ARGS" | sed 's/\t/ /g' | tr -s ' ') trap - ERR info "Booting image using ${VERS}..." + [[ "${DEBUG}" == [Yy1]* ]] && set -x exec qemu-system-x86_64 ${ARGS:+ $ARGS} { set +x; } 2>/dev/null diff --git a/src/network.sh b/src/network.sh index d9af6620..6ae1cef7 100644 --- a/src/network.sh +++ b/src/network.sh @@ -6,6 +6,8 @@ set -Eeuo pipefail : ${DHCP:='N'} : ${MAC:='82:cf:d0:5e:57:66'} +: ${CONTROL_PORTS:=''} + : ${VM_NET_TAP:='qemu'} : ${VM_NET_DEV:='eth0'} : ${VM_NET_MAC:="$MAC"} @@ -146,11 +148,17 @@ configureNAT () { ip link set dev "${VM_NET_TAP}" master dockerbridge + CONTROL_PORT_ARGS='' + for PORT in $CONTROL_PORTS ; do + CONTROL_PORT_ARGS="$CONTROL_PORT_ARGS ! --dport $PORT" + done + # Add internet connection to the VM IP=$(ip address show dev "${VM_NET_DEV}" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/) iptables -t nat -A POSTROUTING -o "${VM_NET_DEV}" -j MASQUERADE - iptables -t nat -A PREROUTING -i "${VM_NET_DEV}" -d "${IP}" -p tcp -j DNAT --to $VM_NET_IP + # shellcheck disable=SC2086 + iptables -t nat -A PREROUTING -i "${VM_NET_DEV}" -d "${IP}" -p tcp $CONTROL_PORT_ARGS -j DNAT --to $VM_NET_IP iptables -t nat -A PREROUTING -i "${VM_NET_DEV}" -d "${IP}" -p udp -j DNAT --to $VM_NET_IP if (( KERNEL > 4 )); then