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..2219392 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..e6016f4 --- /dev/null +++ b/docker/vnc-entrypoint.sh @@ -0,0 +1,79 @@ +#!/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..."' +screen -dmS turbovnc bash -c '/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..c509cd1 --- /dev/null +++ b/vnc.dockerfile @@ -0,0 +1,143 @@ +ARG BASE_IMAGE=debian:trixie-slim +FROM ${BASE_IMAGE} AS base + +ARG BASE_IMAGE +ARG username=lcas +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 \ + sudo \ + wget \ + libglvnd0 \ + libgl1 \ + libglx0 \ + libegl1 \ + libxext6 \ + libx11-6 \ + x11-utils \ + less \ + 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 +RUN wget -q -O- https://packagecloud.io/dcommander/virtualgl/gpgkey | gpg --dearmor >/etc/apt/trusted.gpg.d/VirtualGL.gpg && \ + echo "deb [signed-by=/etc/apt/trusted.gpg.d/VirtualGL.gpg] https://packagecloud.io/dcommander/virtualgl/any/ any main" >> /etc/apt/sources.list.d/virtualgl.list && \ + apt update && apt install -y virtualgl libgl1 && rm -rf /var/lib/apt/lists/* + +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 + +# Install TurboVNC +RUN wget -q -O- https://packagecloud.io/dcommander/turbovnc/gpgkey | gpg --dearmor >/etc/apt/trusted.gpg.d/TurboVNC.gpg && \ + echo "deb [signed-by=/etc/apt/trusted.gpg.d/TurboVNC.gpg] https://packagecloud.io/dcommander/turbovnc/any/ any main" >> /etc/apt/sources.list.d/TurboVNC.list && \ + apt update && apt install -y turbovnc && rm -rf /var/lib/apt/lists/* + +# 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 + +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 + +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 + +# Allow other containers to share windows into this display +RUN echo 'xhost +local: 2>/dev/null' >> ~/.bashrc && \ + echo "if [ -f /etc/bash.bashrc ]; then source /etc/bash.bashrc; fi" >> /root/.bashrc && \ + echo "alias cls='clear'" >> /etc/bash.bashrc && \ + echo 'echo -e "$(printf "%80s" | tr " " "-") \nYou are inside the VNC container,\n - You do not have access to ROS in this terminal\n - You may docker exec into other containers.\n$(printf "%80s" | tr " " "-")\n"' >> /etc/bash.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 + +FROM xfce AS docker-tools + +ARG DOCKER_GID=984 + +# Install Docker (for docker exec etc) +USER root +RUN apt-get update && \ + apt-get install -y ca-certificates curl && \ + install -m 0755 -d /etc/apt/keyrings && \ + curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list && \ + apt-get update && \ + apt-get install -y docker-ce-cli && \ + rm -rf /var/lib/apt/lists/* && \ + groupadd -g $DOCKER_GID docker && \ + usermod -aG docker ${username} + +USER ${username}