2025年8月17日日曜日

Run a Full Linux Desktop in Docker

 

First Ray of Light: The Good Things and the Bad Things

After my failed custom image attempt, I found a promising XFCE-based Debian image on Docker Hub. I downloaded it in minutes and, with a few commands, launched it. When I opened the URL, I was greeted by a fully functional Linux desktop, running right in my browser. The pure geek joy of seeing a complete OS served from inside a Docker container was a feeling I won’t forget. It worked!

The usability was surprisingly decent. LibreOffice and GIMP worked fine, although there was a bit of a lag. I would estimate about 70% of native performance, but still very usable. Firefox launched, too, and I even tried YouTube. That's when I hit the first major hurdle: the colors were dull and washed out. A quick check confirmed my suspicion: the browser was using software rendering. My GPU was sitting idle.

There was another problem I noticed: Flatpak didn't work. Any attempt to install an app from Flatpak failed with errors, so I had to resort to Debian packages. Despite these limitations, seeing a complete Linux desktop running in my browser, served directly from Docker, was a massive win.

Tweaking and Learning

After a few minutes with XFCE, I decided to switch things up and try GNOME as my desktop environment. Big mistake! It took hours of troubleshooting and error-fixing to get it running, and when it finally launched, it was slow and resource-hungry. In the end, I swallowed my pride and reverted to XFCE, and told myself, XFCE may not be flashy, but it’s far more responsive. So let's lean towards practicality.

With my new focus on performance, I decided to revisit my first attempt: building a custom image from scratch. This time, I studied the Dockerfile of the pre-built image I had used previously. I wanted to understand exactly what was going on under the hood, and I wanted to see if I could improve the performance myself. I experimented with a few new configurations, specifically trying to use xrdp instead of the noVNC forwarding method, to see if a different protocol would offer a smoother experience. But I didn't see any difference with xrdp.

To replicate, create a file with the name "dockerfile", paste the code, and run it.

FROM ubuntu:jammy-20230425


RUN apt update && \
    DEBIAN_FRONTEND=noninteractive apt install -y \
        cinnamon locales sudo \
        tigervnc-standalone-server tigervnc-common \
        virtualgl mesa-utils mesa-vulkan-drivers \
        dbus-x11 xterm wget && \
    locale-gen en_US.UTF-8 && \
    update-locale LANG=en_US.UTF-8

# Create user
# Enter the below username and passoword in xrdp login screen
ARG USER=user
ARG PASS=1234
RUN useradd -m $USER -p $(openssl passwd $PASS) && \
    usermod -aG sudo $USER && \
    chsh -s /bin/bash $USER

# Environment for Cinnamon
RUN echo "#!/bin/sh\n\
export XDG_SESSION_DESKTOP=cinnamon\n\
export XDG_SESSION_TYPE=x11\n\
export XDG_CURRENT_DESKTOP=X-Cinnamon\n\
export LIBGL_ALWAYS_INDIRECT=0\n\
exec cinnamon-session" > /home/$USER/.xinitrc && \
    chown $USER:$USER /home/$USER/.xinitrc && chmod +x /home/$USER/.xinitrc

# Setup VNC password
RUN mkdir -p /home/$USER/.vnc && \
    echo $PASS | vncpasswd -f > /home/$USER/.vnc/passwd && \
    chmod 0600 /home/$USER/.vnc/passwd && \
    chown -R $USER:$USER /home/$USER/.vnc

# Start script
RUN echo "#!/bin/bash\n\
export DISPLAY=:1\n\
Xvnc :1 -geometry 1920x1080 -depth 24 -SecurityTypes VncAuth -rfbport 5901 -localhost no &\n\
sleep 2\n\
sudo -u $USER startx &\n\
tail -f /dev/null" > /start && chmod +x /start

EXPOSE 5901

CMD ["/start"]

If all of this sounds like too much work, there’s good news. You don’t have to build your own image to get started or deal with errors. My research led me to two fantastic, ready-to-use solutions that offer a much more streamlined experience.

  • Webtop by LinuxServer.io: This is a great open-source option that provides a variety of Linux desktop flavors pre-packaged as Docker images. It uses noVNC to deliver the desktop straight to your browser, and the setup is straightforward.
  • Kasm Workspaces: This is another open-source option for personal use.

The good thing about these images is that they have everything pre-configured, especially Webtop. You simply pull the Docker image and run it. Once the container is running, you can access your Linux by entering the URL. I found the performance to be much better than anything I had tried previously, and, importantly, had audio pass-through, which I didn't find with Kasm images.

To run Webtop, open Windows CMD and paste this code

docker run -d ^
--name webtop-xfce ^
-e PUID=1000 ^
-e PGID=1000 ^
-e TZ=Etc/UTC ^
-p 3000:3000 ^
--shm-size=1gb ^
lscr.io/linuxserver/webtop:latest

Why Is It Difficult to Run Linux in Docker?

So, now that I have understood that running a full desktop environment inside a container and expecting it to behave like a normal desktop on Windows is possible but painful, fragile, and much more cumbersome than running a VM. The primary reasons for these are:

  • Containers are not isolated Operating Systems: Docker containers share the host kernel. This is what makes them lightweight and great for single services. Whereas desktop environments expect system services like (systemd, logind, udev, DBus) and device access to be available. Containers don’t provide that by default.
  • No built-in display servers: Linux GUIs need a compositor/display server (X11 or Wayland). A container does not provide one, so we have to do that ourselves.
  • GPU access: Containers don’t virtualize GPUs by default, so you must pass device nodes into the container. And on Windows, there’s an additional WSL layer to cross.



0 件のコメント:

コメントを投稿