mviereck / x11docker

Run GUI applications and desktops in docker and podman containers. Focus on security.
MIT License
5.62k stars 378 forks source link

Run arbitrary application whose preferred display server, x11 or Wayland, is unknown #31

Closed oxwivi closed 6 years ago

oxwivi commented 6 years ago

Is there catch-all command to display the application regardless of the window system it uses or other attributes that may or may not be known to the user?

mviereck commented 6 years ago

Currently all applications available will support X11. Some also support Wayland. All current Wayland compositors normally run Xwayland to support X11 applications, too.

It will take some (or a lot of) years until Wayland compositors without Xwayland will be present as regular desktop environments. Currently only some developers will occasionally run a pure Wayland environment to test their applications.

So far, an easy general solution that will work for some years and for 99,9% of use cases will be a pure X11 setup for docker containers.

Example with x11docker:

x11docker x11docker/xfce xfce4-terminal

Example without x11docker, as in https://unix.stackexchange.com/questions/330366/how-can-i-run-a-graphical-application-in-a-container-under-wayland :

xhost +SI:localuser:$(id -un)
docker run --user=$(id -u):$(id -g) \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    --ipc=host \
    x11docker/xfce xfce4-terminal

If you are running a Wayland compositor like Gnome 3 or Sway, you can provide both Wayland and X11 access. With environment variable XDG_SESSION_TYPE (values: x11 or wayland) you can indicate that Wayland should be preferred by the application.

Example with x11docker:

x11docker --hostdisplay --hostwayland \
    --env XDG_SESSION_TYPE=wayland \
    x11docker/xfce xfce4-terminal

Example without x11docker:

docker run --user=$(id -u):$(id -g) \
    -e XDG_RUNTIME_DIR=/tmp \
    -e WAYLAND_DISPLAY=$WAYLAND_DISPLAY \
    -v $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY:/tmp/$WAYLAND_DISPLAY  \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    --user=$(id -u):$(id -g) \
    --ipc=host \
    --env XDG_SESSION_TYPE=wayland \
    x11docker/xfce xfce4-terminal

A bit special are QT5 applications (most of KDE). To use Wayland they need -e QT_QPA_PLATFORM=wayland and must be started with dbus-launch. You could add that in general, but there is a pitfall: GTK3 application fail with dbus-launch. I recommend just to leave that away; QT5 applications will use X11 then.


(Edit: I have removed the workaround with --entrypoint env. I have fixed the ENTRYPOINT issue in x11docker images. If you have already pulled an image, please pull a fresh one).

oxwivi commented 6 years ago

BTW, since it's possible without x11docker what exactly is its use-case?

mviereck commented 6 years ago

Sharing host display :0 is a security issue. For example, container application can remotly control host applications over X (compare xdotool) and can run keyloggers (compare xinput test or xev).
x11docker provides possibilities to avoid X security leaks. Just install X servers like Xephyr, xpra or nxagent and x11docker will automatically use them to avoid X security leaks.

Furthermore it provides some comfortable options, e.g. to use hardware acceleration and pulseaudio sound.

A non obvious feature is dropping container capabilities to a bare minimum (compare man capabilities). That improves container security as applications cannot abuse capabilities they don't have. Important case: applications running as root in container may break out and access the host. x11docker runs container with an unprivileged user and drops the capability for user switching. Container applications cannot become root in a default x11docker setup.

Edit: For most cases you get improved isolation without missing application functionality with docker run options --cap-drop=ALL --security-opt=no-new-privileges. To adress the zombie reaping issue, add docker run option --init. x11docker does this settings by itself.

oxwivi commented 6 years ago

This is way off-topic, but would you happen to know how exactly I'm supposed to create simplest dockers with to persistently run apps like Google Chrome, Firefox and Steam? Previously I preferred LXC-based Canonical project, Libertine, but it's probably on track to deprecation since Wayland and GNOME Shell.

I found these two for reference, sameersbn/browser-box:1.0.1-3 and Run Firefox or Google Chrome into a Docker container. but I don't understand what roles USER and ENV plays in those dockerfiles and if I'll need them for a minimal persistent container just for isolating things like browsers, Steam and Wine.

mviereck commented 6 years ago

The browser-box does a lot of custom setup dispersed on several files, I don't want to go through all this.

The firefox example is easier to understand. It creates a user developer with UID 1000 and GID 1000 in Dockerfile to avoid running firefox as root. USER developer advices docker to run the image as this user. ENV HOME /home/developer advices docker to set environment variable HOME to this users home directory. It makes sense to run docker images as unprivileged user. Running root in container is quite common, but a bad idea. Though, the docker run example does not isolate firefox from host display :0.

x11docker does similar setups on its own. For many applications it is quite easy to set up valid docker images. x11docker cares for user creation itself.


Example for midori browser:

FROM debian:stretch-slim
RUN apt-get update
RUN apt-get install -y --no-install-recommends midori ca-certificates
CMD midori

Build with: docker build -t midori /PATH/TO/DOCKERFILE/ Run with: x11docker midori


Some applications need some custom setup. For example, recent firefox versions fail in this setup, for unknown reasons they need docker option --ipc=host or x11docker option --hostipc. Compare https://github.com/jessfraz/dockerfiles/issues/360.

Example: x11docker --hostipc jess/firefox


wine is even more complicated to satisfy all dependencies. I provide image x11docker/lxde-wine. Examples: x11docker --desktop x11docker/lxde-wine x11docker x11docker/lxde-wine playonlinux


chromium needs option --no-sandbox as its own sandbox features (to isolate browser tabs) do not work within a container. (At least, I did not investigate if/how it would be possible. Maybe adding some non-default capabilities would allow it). Dockerfile for chromium:

FROM debian:stretch-slim
RUN apt-get update
RUN apt-get install -y --no-install-recommends chromium ca-certificates
CMD chromium --no-sandbox

Build image like midori example and run with x11docker chromium _(Edit: I tried a bit and found that chromium can run with its own sandbox features/without --no-sandbox if using x11docker options --cap-default --sys-admin. But I do not recommend that; --sys-admin adds capability SYS_ADMIN and makes container nearly root equivalent. You have the choice between either good isolation from host with chromium --no-sandbox or with quite bad isolation from host but good browser tab isolation with x11docker options --cap-default --sys-admin)._

oxwivi commented 6 years ago

Damn, that's more over the place than I was prepared for. How can I troubleshoot in case something doesn't work? Obviously I can't ask for your assistance every time something goes wrong. Like --hostipc, don't even know what it is so I can't even begin to suspect any app to not work because of it.

Also, for development purposes, I remember Python's virtualenv not playing nice with LXC shells, I wonder if docker would be beset by similar issues. Have you heard of it?

mviereck commented 6 years ago

How can I troubleshoot in case something doesn't work? Obviously I can't ask for your assistance every time something goes wrong.

Sure, you can ask. Just try out; as I said, most apps will run out of the box. You just picked some examples that are rather special. Build your images, run them, and if you are stuck, open a ticket and I'll look at that. Most times it makes sense to run x11docker with option --verbose and to store the output at https://pastebin.com/.

Often the application itself will show usefull error messages. To get application output only, run with --stdout --stderr instead of --verbose.

One approach of debugging is to run with options --cap-default --hostipc --hostnet, maybe even with --user=root. That degrades container isolation a lot. If that helps, reduce the options to encircle the issue.

Also, for development purposes, I remember Python's virtualenv not playing nice with LXC shells, I wonder if docker would be beset by similar issues. Have you heard of it?

I've not heard of it. I had a short look; it seems to set up something like a chroot environment. I cannot assess if that will work in docker. Just try out, open a ticket and report; maybe I'll have ideas if I see some error messages.


Rather hard approaches of degrading container isolation for debugging is to allow all linux capabilities. It is not directly an x11docker option, but possible. You would need docker run option --cap-add=ALL. You can add docker run options after -- in x11docker commands. Example: x11docker --cap-default -- --cap-add=ALL x11docker/lxde pcmanfm Same way you can add docker run option --privileged, normally a no-go as it destroys nearly all isolation. But it may help for debugging and encircling issues.

oxwivi commented 6 years ago

I've a couple of more unrelated questions:

mviereck commented 6 years ago

can I use the root dir of the local system as base for docker containers? That'd save me the effort to install things like font packs and stuff.

I've never tried, and I doubt it would work. docker creates some files like /etc/hostname that would be overwritten on host. Likely you would destroy your host. Though, it is possible to mount / at a different location in container and 'chroot` into it. But I am not familar with that.

Sharing folders from host is possible with option --sharedir DIR.

I would rather recommend to create an image based on the same system as your host. Then it should be possible to mount some systemhost folders/libraries into container. But rather ask someone else, I can only tell vaguely.

I understand I can specify home/ dir for the container, but what about root dir in case I want persistent server containers, as in run things like nginx without web root getting wiped everytime?

I don't really understand the question. nginx is often used in containers, but I've never used it. I don't know what it needs and how to set it up. If it needs additional privileges or group memberships, x11docker can add them.

oxwivi commented 6 years ago

Can't we provide the root dir as copy-on-write image? As in, if it needs to touch the hostname, it'll save the change only. I believe btrfs does it on the filesystem level.

From what I understand, every time I run the container, it starts with a fresh root directory. Wouldn't that wipe out the document root with my HTML files?

mviereck commented 6 years ago

Can't we provide the root dir as copy-on-write image? As in, if it needs to touch the hostname, it'll save the change only.

I really don't know. Though, it is an interesting approach to use the host as a base instead of an image. If you find out more about this, please tell me.

Wouldn't that wipe out the document root with my HTML files?

If you mount a directory from host to the HTML storage location, the HTML files will be preserved. x11docker provides option --sharedir, and that uses docker run option --volume.

docker also provides some sort of persistant data volume containers, but I did not investigate. I trust more in shared host directories.

mviereck commented 6 years ago

I'll close this ticket as the origin question is answered. Feel free to ask further questions here, or to open new tickets.

In general, it's a good idea to open new tickets for new questions, may they big or small. It helps to find again topics later, and helps others who are looking through the issues.

mviereck commented 6 years ago

Can't we provide the root dir as copy-on-write image? As in, if it needs to touch the hostname, it'll save the change only.

I really don't know. Though, it is an interesting approach to use the host as a base instead of an image. If you find out more about this, please tell me.

I am not sure, but firejail maybe provides something similar.