As we know, we can use host’s wayland socket to display container’s gui app.
overview-gui-inside-containers
So, why won’t we go farther, containerlize wayland compositor and gui apps in separate containers.
Please, do forgive my poor English, I don’t how to express this in English. What I want to say is like the image, “passthrough” display to container, so we will not mess up host environment, containerlizing gui apps, so the wayland compositor container environment will be relatively clean. For example, only the gui app container need to install gtk3.
Important thing first, we need install a wayland compositor in host, so we can use the wayland socket.
I’m using sway, you can choose anything you like.
I edited sway config like this to hide titlebar and swaybar, but you can skip:
~/.config/sway/config
default_border none
default_floating_border none
font pango:monospace 0
titlebar_padding 1
titlebar_border_thickness 0
#bar {
# position top
# When the status_command prints a new line to stdout, swaybar updates.
# The default just shows the current date and time.
# status_command while date +'%Y-%m-%d %I:%M:%S %p'; do sleep 1; done
# colors {
# statusline #ffffff
# background #323232
# inactive_workspace #32323200 #32323200 #5c5c5c
# }
#}
Let’s say, I want firefox saves file in $HOME/Downloads, and not directly showing in host wayland compositor, and in a separate container. To do that the container istalled firefox must access $HOME/Downloads and $XDG_RUNTIME_DIR in wayland compositor container.
Thank to incus, we can mount a volume between containers, so we put $HOME and $XDG_RUNTIME_DIR in the volume,and problem solved.
Because I’m lazy, $XDG_RUNTIME_DIR will stay in $HOME. It will be better they are in separate volumes.
incus storage volume create default home --type=filesystem
incus profile create mount
incus profile edit mount
mount
config: {}
description: share volume between containers
devices:
home:
pool: default
type: disk
source: home
path: /home/
propagation: private
name: mount
And profile for wayland socket and gpu accelerate. By default, sway will create wayland-1 as wayland socket.
wayland
config: {}
description: Let containers use host display
devices:
waylandSocket:
type: proxy
bind: container
connect: unix:/run/user/1000/wayland-1
listen: unix:/mnt/wayland-1
mode: '0700'
security.gid: '1000'
security.uid: '1000'
gid: '1000'
uid: '1000'
mygpu:
type: gpu
gid: '1000'
uid: '1000'
name: wayland
So let’s create wayland compositor container. I’m using labwc, so it will call labwc.
incus launch images:alpine/3.19 labwc -p default -p wayland -p mount
incus exec labwc ash
apk update
apk upgrade
apk add mesa-dri-gallium labwc labwc-doc font-dejavu
Wayland won’t let root use gui, so create one called lxc.
adduser -s /bin/ash -g "lxc" lxc
adduser lxc video
adduser lxc input
It’s a wayland compositor thing, they need config before start. Alpine linux won’t auto set XDG_RUNTIME_DIR without seatd manager. And we need point it to use host(sway) wayland socket. Start labwc, and you will see a black screen with a cursor.
su -l lxc
mkdir -p ~/.config
cp -r /usr/share/doc/labwc/ ~/.config/
mkdir -pm 0700 ~/.run/
ln -s /mnt/wayland-1 /home/lxc/.run/wayland-1
export XDG_RUNTIME_DIR=/home/lxc/.run/
export WAYLAND_DISPLAY=wayland-1
labwc
Then gui app container. I’m using firefox, so it will call firefox.
Yes, same user, same uid, same $HOME, same $XDG_RUNTIME_DIR.
We use wayland-0(labwc wayland socket) this time, so firefox will show in container wayland compositor(labwc).
incus launch images:alpine/3.19 firefox -p default -p mount
apk update
apk upgrade
apk add font-dejavu firefox
adduser -s /bin/ash -g "lxc" lxc
su -l lxc
export XDG_RUNTIME_DIR=/home/lxc/.run/
export WAYLAND_DISPLAY=wayland-0
export MOZ_ENABLE_WAYLAND=1
firefox