diff --git a/.github/workflows/_build-image.yaml b/.github/workflows/_build-image.yaml index 23832aa..1241d02 100644 --- a/.github/workflows/_build-image.yaml +++ b/.github/workflows/_build-image.yaml @@ -12,7 +12,7 @@ on: required: true type: string ros_distro: - required: true + required: false type: string dockerfile: required: true @@ -79,4 +79,4 @@ jobs: labels: ${{ steps.meta.outputs.labels }} build-args: | BASE_IMAGE=${{ inputs.base_image }} - ROS_DISTRO=${{ inputs.ros_distro }} \ No newline at end of file + ROS_DISTRO=${{ inputs.ros_distro }} diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index f2c6942..2173e3a 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -10,6 +10,16 @@ on: jobs: + # ── VNC Container Building ──────────────────────-──────────────────────── + vnc: + uses: ./.github/workflows/_build-image.yaml + with: + base_image: debian:trixie-slim + push_image: vnc + dockerfile: vnc.dockerfile + architectures: linux/amd64,linux/arm64 + secrets: inherit + # ── Level 0: no dependencies ────────────────────────────────────────────── ros-humble: diff --git a/docker/vnc-entrypoint.sh b/docker/vnc-entrypoint.sh new file mode 100644 index 0000000..76d9a93 --- /dev/null +++ b/docker/vnc-entrypoint.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +echo +echo "****************************************************************************************************************************************" +echo "AOC VNC container starting..." +echo "****************************************************************************************************************************************" + + +echo "starting turbovnc" +sudo rm -rf /tmp/.X1-lock /tmp/.X11-unix/X1 > /dev/null 2>&1 +screen -dmS turbovnc bash -c 'VGL_DISPLAY=egl VGL_FPS=30 /opt/TurboVNC/bin/vncserver :1 -depth 24 -noxstartup -securitytypes TLSNone,X509None,None 2>&1 | tee /tmp/vnc.log; read -p "Press any key to continue..."' +# wait for VNC to be running + +echo "waiting for display to be up" +while ! xdpyinfo -display :1 2> /dev/null > /dev/null; do + sleep .1 +done +echo "display is up" + +echo "starting xfce4" +screen -dmS xfce4 bash -c 'DISPLAY=:1 /usr/bin/xfce4-session 2>&1 | tee /tmp/xfce4.log' +while [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; do + if pgrep xfce4-session > /dev/null; then + XFCE_PID=$(pgrep xfce4-session) + export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$XFCE_PID/environ|cut -d= -f2-|tr -d '\0') + fi + sleep .1 +done +echo "xfce4 up" + +echo "starting novnc ${NOVNC_VERSION}" +screen -dmS novnc bash -c '/usr/local/novnc/noVNC-${NOVNC_VERSION}/utils/novnc_proxy --vnc localhost:5901 --listen 5801 2>&1 | tee /tmp/novnc.log' + +DISPLAY=:1 xhost +local: 2>/dev/null +echo "xhost +local: applied to :1" + +# ensure wallpaper/panels are applied; start xfdesktop if missing +( + sleep 8 + export DISPLAY=:1 + export DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" + + # start xfdesktop if not running so it can apply the wallpaper + if ! pgrep -u "$USER" xfdesktop > /dev/null 2>&1; then + xfdesktop --daemon > /dev/null 2>&1 || true + fi + + WALLPAPER="/usr/share/backgrounds/xfce/aoc_wallpaper.jpg" + + # apply wallpaper for monitor0 (add others if needed) + xfconf-query -c xfce4-desktop -np /backdrop/screen0/monitor0/image-path -t string -s "$WALLPAPER" > /dev/null 2>&1 + xfconf-query -c xfce4-desktop -np /backdrop/screen0/monitor0/last-image -t string -s "$WALLPAPER" > /dev/null 2>&1 + xfconf-query -c xfce4-desktop -np /backdrop/screen0/monitor0/workspace0/last-image -t string -s "$WALLPAPER" > /dev/null 2>&1 + xfconf-query -c xfce4-desktop -np /backdrop/screen0/monitor0/image-show -t bool -s true > /dev/null 2>&1 + + # remove secondary panel if present + xfconf-query -c xfce4-panel -p /panels/panel-2 -r > /dev/null 2>&1 || true + xfce4-panel --reload > /dev/null 2>&1 || true + + xfdesktop --reload > /dev/null 2>&1 || true +) & + +echo +echo "****************************************************************************************************************************************" +echo "VNC Desktop ready. Open your browser at http://localhost:5801/vnc.html?autoconnect=true or another hostname and port you may have forwarded." +echo "****************************************************************************************************************************************" +echo + +echo >&2 + +# This script can either be a wrapper around arbitrary command lines, +# or it will simply exec bash if no arguments were given +if [[ $# -eq 0 ]]; then + exec "/bin/bash" +else + exec "$@" +fi + diff --git a/vnc.dockerfile b/vnc.dockerfile new file mode 100644 index 0000000..7cee0fe --- /dev/null +++ b/vnc.dockerfile @@ -0,0 +1,154 @@ +ARG BASE_IMAGE=debian:trixie-slim +FROM ${BASE_IMAGE} AS base + +ARG BASE_IMAGE +ARG username=aoc +ENV BASE_IMAGE=${BASE_IMAGE} + +ENV DEBIAN_FRONTEND=noninteractive \ + DISPLAY=:1 \ + VNC_PORT=5900 \ + NOVNC_PORT=5801 \ + RESOLUTION=1366x768x24 + +# Install timezone +RUN ln -fs /usr/share/zoneinfo/UTC /etc/localtime \ + && export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get install -y --no-install-recommends tzdata \ + && dpkg-reconfigure --frontend noninteractive tzdata \ + && rm -rf /var/lib/apt/lists/* + +# Install packages +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + gnupg2 \ + lsb-release \ + nano \ + sudo \ + python3-setuptools \ + wget \ + libglvnd0 \ + libgl1 \ + libglx0 \ + libegl1 \ + libxext6 \ + libx11-6 \ + x11-utils \ + python3-minimal \ + python3-pip \ + python3-numpy \ + python3-venv \ + less \ + tmux \ + screen \ + unzip \ + x11-apps \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user +RUN useradd -m -s /bin/bash -G video,sudo ${username} && \ + echo "${username} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Fix /tmp/.X11-unix permissions +RUN mkdir -p /tmp/.X11-unix && \ + chmod 1777 /tmp/.X11-unix + +# Install VirtualGL +ARG TARGETARCH +ENV DEBIAN_FRONTEND=noninteractive +RUN curl -L -O https://github.com/VirtualGL/virtualgl/releases/download/3.1.1/virtualgl_3.1.1_${TARGETARCH}.deb && \ + apt-get update && \ + apt-get -y install ./virtualgl_3.1.1_${TARGETARCH}.deb && \ + rm virtualgl_3.1.1_${TARGETARCH}.deb && rm -rf /var/lib/apt/lists/* +RUN curl -L -O https://github.com/TurboVNC/turbovnc/releases/download/3.1.1/turbovnc_3.1.1_${TARGETARCH}.deb && \ + apt-get update && \ + apt-get -y install ./turbovnc_3.1.1_${TARGETARCH}.deb && \ + rm turbovnc_3.1.1_${TARGETARCH}.deb && rm -rf /var/lib/apt/lists/* +RUN addgroup --system vglusers && adduser ${username} vglusers + + +# Install noVNC +ENV NOVNC_VERSION=1.4.0 +ENV WEBSOCKETIFY_VERSION=0.10.0 + +RUN mkdir -p /usr/local/novnc && \ +curl -sSL https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.zip -o /tmp/novnc-install.zip && \ +unzip /tmp/novnc-install.zip -d /usr/local/novnc && \ +cp /usr/local/novnc/noVNC-${NOVNC_VERSION}/vnc.html /usr/local/novnc/noVNC-${NOVNC_VERSION}/index.html && \ +curl -sSL https://github.com/novnc/websockify/archive/v${WEBSOCKETIFY_VERSION}.zip -o /tmp/websockify-install.zip && \ +unzip /tmp/websockify-install.zip -d /usr/local/novnc && \ +ln -s /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION} /usr/local/novnc/noVNC-${NOVNC_VERSION}/utils/websockify && \ +rm -f /tmp/websockify-install.zip /tmp/novnc-install.zip && \ +sed -i -E 's/^python /python3 /' /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION}/run + +RUN cat < /usr/share/glvnd/egl_vendor.d/10_nvidia.json +{ + "file_format_version" : "1.0.0", + "ICD" : { + "library_path" : "libEGL_nvidia.so.0" + } +} +EOF + +FROM base AS xfce + +# Install XFCE4 +RUN apt-get update && \ + apt-get -y install \ + xfce4-session \ + xfce4-panel \ + xfdesktop4 \ + konsole \ + && rm -rf /var/lib/apt/lists/* +RUN apt-get purge -y xfce4-screensaver + +# thunar + +COPY docker/vnc-entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT [ "/entrypoint.sh" ] + +# Set default XFCE wallpaper -- doesnt work +# COPY aoc_wallpaper.jpg /usr/share/backgrounds/xfce/aoc_wallpaper.jpg +# RUN mkdir -p /home/${username}/.config/xfce4/xfconf/xfce-perchannel-xml && \ +# cat > /home/${username}/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-desktop.xml <<'EOF' +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# +# EOF +RUN chown -R ${username}:${username} /home/${username}/.config + +# Allow other containers to share windows into this display +RUN echo 'xhost +local: 2>/dev/null' >> ~/.bashrc + +EXPOSE 5801 + +USER ${username} +ENV HOME=/home/${username} +WORKDIR ${HOME} +RUN mkdir -p ${HOME}/.local/bin + +ENV DISPLAY=:1 +ENV TVNC_VGL=1 +ENV VGL_ISACTIVE=1 +ENV VGL_FPS=25 +ENV VGL_COMPRESS=0 +ENV VGL_DISPLAY=egl +ENV VGL_WM=1 +ENV VGL_PROBEGLX=0 +ENV LD_PRELOAD=/usr/lib/libdlfaker.so:/usr/lib/libvglfaker.so +ENV SHELL=/bin/bash \ No newline at end of file