mviereck / x11docker

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

Question: gui installer #201

Closed faxm0dem closed 4 years ago

faxm0dem commented 4 years ago

Thanks for your awesome work! I have a question on how to install software into docker, which runs an installer. Basically, I'd like to do x11docker build -f Dockerfile-for-installer

mviereck commented 4 years ago

Can you give me an example? Linux applications can normally be installed with non-interactive commands.

If the installer has some yes/no questions that cannot be avoided e.g. with cli options, you can try to automate them with command expect.

A graphical installation during docker build is not possible. (Edit: It is possible, see below)

faxm0dem commented 4 years ago

You're right, but there are exceptions :-) As it happens, I was able to workaround this by using yes, but there are many proprietary tools that require graphical user interaction during install. In my case it was Quartus Programmer (but as I said I managed to workaround it).

mviereck commented 4 years ago

As it happens, I was able to workaround this by using yes.

ok, good.

there are many proprietary tools that require graphical user interaction during install.

Just an idea in general: As far as I can see there is no way to interactively build a Docker image, neither cli nor graphical.

But it might work to run Xvfb during build and to do mouse clicks and key presses with xdotool. Run Xvfb, installer and xdotool all in one RUN line.

And one ugly workaround: Run x11docker with --user=root, install your application interactively, and create a new image from the running container with docker commit.

eine commented 4 years ago

The approach I have used with EDA tools is to install them in a container (with x11docker/runx) to a specific location (say /opt/quartus). Then, save the location to a tarball and COPY or ADD it in the Dockerfile. Hence, there are two different Dockerfiles: the one with build dependencies, which you will use as a container only; and the one with runtime dependencies, which you will use to generate the final image.

Of course, this will only work as long as the tools install all their resources in the specified location. If they change other resources in the system, it might not work. This is the case with e.g. configuration of udev to configure/program the boards. Nevertheless, when working with containers, this needs special care anyway.

EDIT

This is similar to @mviereck's suggestion to use docker commit. However, it is slightly cleaner, since build and runtime dependencies are explicitly separated.

mviereck commented 4 years ago

I am just thinking about some trickery to get a GUI during docker build. Docker does not provide an interactive cli and does not allow to share an X unix socket. But it might be possible to run an X server on host and to access it over TCP.

mviereck commented 4 years ago

It works! Proof of concept:

Run X server:

$ x11docker --xephyr --xoverip --no-auth --display=30 --xhost=+
 DISPLAY=172.17.0.1:30 XDG_RUNTIME_DIR=/run/user/1000

Keep the X server running and provide the shown DISPLAY in Dockerfile:

FROM x11docker/fvwm
RUN env DISPLAY=172.17.0.1:30 xterm

Edit: It is possible to provide DISPLAY on cli instead in Dockerfile. Add ARG DISPLAY to Dockerfile:

FROM x11docker/fvwm
ARG DISPLAY
RUN xterm

Build with:

docker build --build-arg DISPLAY=172.17.0.1:30 [...]
eine commented 4 years ago

That's actually very interesting! I thought it would not be possible with the standard tool; but buildkit might be required: https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md

In the test you run, does the build freeze until you close xterm? How does it work with buildkit enabled?

mviereck commented 4 years ago

I thought it would not be possible with the standard tool; but buildkit might be required

I did not know of it before. Interesting. Might even allow to share a unix socket. My idea was just that docker build allows internet access, so a TCP connection to X could be possible.

In the test you run, does the build freeze until you close xterm?

Yes. Docker waits until xterm is done.

How does it work with buildkit enabled?

Just checked, works well.

mviereck commented 4 years ago

I've published a How-To in the wiki:

docker build with interactive GUI

faxm0dem commented 4 years ago

you rock :-) thanks a bunch for your enthusiasm and support!

mviereck commented 4 years ago

@1138-4EB I assume this should work on MS Windows, too. You do not need --xoverip because it is already default on MS Windows.

There is one special point: I found that --no-auth is not enough on Linux, but also needs xhost + for unknown reasons. xhost +SI:localuser:root failed. I am not sure if the same issue occurs on MS Windows.

In MSYS2 this setup may fail because it does not provide xhost. In Cygwin you can just use the command example without --xephyr and it should work. In WSL it should work with runx and xhost +.

faxm0dem commented 4 years ago

what about xhost +local: ?

mviereck commented 4 years ago

what about xhost +local: ?

I've tried that. It fails, too, xterm shows No protocol specified.

Alternatively cookie authentication could be used, but the setup to provide the cookie during build would be rather complicated.

Normally xhost + is a no-go. It would be nice to find a better and elegant solution.

mviereck commented 4 years ago

I found that the setup works with without --xhost + and --no-auth only if I set docker build option --network=host.

Comparing security:

Probably the --network=host solution is less bad. I've adjusted the wiki page accordingly.

I am still surprised that X over TCP/IP without cookie authentication fails in a regular docker build. I thought x11docker --no-auth --xoverip would be essentially equal to xhost +