Running graphic apps in Docker: AWS WorkSpaces
Tags: tutorial, docker, aws, security
Published: 2022-12-29 12:19:18

---
title: 'Running graphic apps in Docker: AWS WorkSpaces'
published: true
description: How to run GUI apps using X.Org and Docker in Linux or Windows
tags: 'tutorial, docker, aws, security'
cover_image: 'https://raw.githubusercontent.com/cloudx-labs/posts/main/posts/navarroaxel/assets/gui-apps-docker-cover.jpg'
id: 1253471
---

As a Linux user, I need to connect to an Amazon WorkSpace but the client app can only be run in specific old, but maintained, versions of Ubuntu. I've tried with the latest Ubuntu version but it haven't worked, so created a virtual machine with Ubuntu Focal 20.04 but this setup used 14GB of disk space 😵 only to open a window application. This didn't make any sense and also included issues when sharing the clipboard from the host to the VM and then to the virtual desktop hosted in Amazon. 🙄
Then, I remembered that we can run graphic applications using Docker. Let's see how to connect a container to the host's [X Window System](https://en.wikipedia.org/wiki/X_Window_System).

## Creating the Docker image

The following Dockerfile builds the image using Ubuntu Focal 20.04, and installs the Amazon WorkSpace client:

```Dockerfile
FROM ubuntu:focal

ENV DEBIAN_FRONTEND=noninteractive

RUN apt update && \
  apt install -y libusb-1.0-0 wget xauth && \
  wget -q -O - https://workspaces-client-linux-public-key.s3-us-west-2.amazonaws.com/ADB332E7.asc | apt-key add - && \
  echo "deb [arch=amd64] https://d3nt0h4h6pmmc4.cloudfront.net/ubuntu focal main" > /etc/apt/sources.list.d/amazon-workspaces-clients.list && \
  apt remove -y wget && \
  apt update && \
  apt install -y workspacesclient && \
  touch /root/.Xauthority && \
  rm -rf /var/lib/apt/lists/*
```

💡 `libusb-1.0-0` is a dependency of Amazon WorkSpaces.

The `DEBIAN_FRONTEND=noninteractive` environment is used to skip the Ubuntu’s prompt asking for our time zone.

Build the image with the following command:

```bash
docker build -t workspace .
```

The Docker image's size is 1.2GB, a reduction of 91% in comparison to the 14GB of the virtual machine.

## Starting the container

Now, we can run the container!

```bash
docker run --name ws --network=host -e DISPLAY -v /tmp/.X11-unix -it workspace
```

We need to share the `.X11-unix/` directory where the connection [socket](https://en.wikipedia.org/wiki/Unix_domain_socket) is located, where `DISPLAY` is the name of the host's display.

The `--network=host` argument makes the container use the same host's network so the container does not get its own IP address. This avoids the container being network isolated. 🪛

## Starting the GUI application

Before starting the app we must authenticate the X Window System of the container with the host.

Get the authorization entry of the host using the `xauth` command:

```bash
xauth list
```

Copy the output of the command and run this in the container (replacing the placeholders with the values from the clipboard):

```bash
xauth add <display_name> <protocol_name> <hex_key>
```

Now you are able to start GUI applications inside the container! 🎉

```bash
/opt/workspacesclient/workspacesclient
```

## Alternative: use VNC instead of X11

We need to make a few changes to run a VNC server in the container:

```Dockerfile
FROM ubuntu:focal

ENV DEBIAN_FRONTEND=noninteractive

RUN apt update && \
  apt install -y libusb-1.0-0 gpg wget x11vnc xvfb && \
  wget -q -O - https://workspaces-client-linux-public-key.s3-us-west-2.amazonaws.com/ADB332E7.asc | apt-key add - && \
  echo "deb [arch=amd64] https://d3nt0h4h6pmmc4.cloudfront.net/ubuntu focal main" > /etc/apt/sources.list.d/amazon-workspaces-clients.list && \
  apt remove -y wget && \
  apt update && \
  apt install -y workspacesclient && \
  rm -rf /var/lib/apt/lists/*

RUN echo "exec /opt/workspacesclient/workspacesclient" > ~/.xinitrc && \
  chmod +x ~/.xinitrc

CMD ["x11vnc", "-create", "-forever"]
```

The `x11vnc` command will start an X11 session in the container launching the application specified in the `~/.xinitrc` file.

```bash
docker build -t workspace .
```

Then, we can run the container:

```bash
docker run --name ws -it workspace
```

But how can we know the IP address of the container? Just check it with the following command:

```bash
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ws
```

Now you can connect to the VNC server. 🔌

## Conclusion

We can run graphic applications that work in specific Linux distros using Docker 🐋, by connecting directly to our X Window System. This uses less memory and disk space than a VM.

You can get the same in Windows as the host using [Xming](https://sourceforge.net/projects/xming/).

`xauth` could be used in conjunction with SSH to run remote GUI apps 😉 in our local, but that's for another post.

Alternatively, you can start a VNC server in a container allowing more flexibility either if you use macOS, or if you can't connect using X11 because you're using [Wayland](https://en.wikipedia.org/wiki/Wayland_(display_server_protocol)). But this doesn't feel like a native window on your OS.