Set up GUI in Container
- Find a Suitable GUI Image
- Install Necessary Packages in the GUI Image
- Create a Labelling App Image
- Update the Labelling App Image
- PyopenGL Issue
- Lessons Learned: Overcoming Hurdles
- Refer
Recently, I found myself delving into a project that demanded running a labeling application built on the Vispy framework. Originally developed on a Windows Subsystem for Linux (WSL) environment, attempting to run it on Ubuntu led to OpenGL-related errors, such as:
Fig1 Error1
Fig2 Error2
I tried pip3 install PyOpenGL==3.1.7
to change its version. But both of them has the issue that from OpenGL import GL
would fail. Fearing potential system instability, I opted to encapsulate the application within a Docker container.
Find a Suitable GUI Image
As the task involved visualization and manual labeling, I scoured GitHub and stumbled upon a publicly shared repository named gui-docker. This repository offered a VNC-enabled GUI setup, which perfectly suited my needs. Setting it up was straightforward:
git clone https://github.com/bandi13/gui-docker
cd {path to gui-docker}
docker build .
Upon successful image creation, running docker images -a
confirmed the existence of a new image named gui-docker
. Subsequently, launching the container and accessing it was achieved using:
docker run <image id> -it --name <container name> bash
Additional terminal access to the running container was facilitated through docker exec -it <container id> bash
To ensure GUI functionality, running xeyes
within the container shell and navigating to localhost:5901
in a web browser displayed a pair of eyes
Install Necessary Packages in the GUI Image
Customizing the container to accommodate project-specific requirements involved installing essential packages and addressing user permission concerns.
You can note down the packages installed on this GUI Container and finalize it as a Dockerfile. The Dockerfile for my repository looked as follows:
# Use Ubuntu 22.04 as base image
FROM bandi13/gui-docker
USER root
# Update the system
RUN apt-get update
RUN apt-get install -y x11-apps
# Install vim
RUN apt-get install -y vim
RUN apt-get install -y git
# -y for confirmation
# Install libglfw3
RUN apt-get install -y libglfw3
# Install pip
RUN apt-get install -y python3-pip
RUN apt-get install -y python3-tk
RUN apt-get install -y libglib2.0-0
RUN pip install vispy pyopengltk
# Copy requirements.txt to the docker image and install Python packages
COPY requirements.txt .
RUN pip install -r requirements.txt
Noteworthy was the adjustment of the user to root during image creation to facilitate hassle-free package installations
The base image
gui-docker
would assign the user as non-root user
Create a Labelling App Image
Utilizing this Dockerfile, a labelling app image would be created. And the user would be the root.
For setting up a container from this new image, suggest to use docker-compuse.yaml
, especially if the container requires several volumne mount or port information. The docker-compose.yaml
format would be like the following:
version: '3' # compose file version
services:
gui-dairy-farm-dataset-v1:
image: veraz00/gui-dairy-farm-dataset-v1:v1
volumes:
- /home/linlin/Workspace/01_FeedRunnerOfficial/dairy-farm-dataset:/dairy-farm-dataset
- /home/linlin/Dataset/01_FeedRunnerOfficial:/Dataset
environment:
- DISPLAY=:0
- VNC_PASSWD=123456
shm_size: 256m
ports:
- "5901:5901"
stdin_open: true # open the standard input
tty: true # open the terminal
restart: "no"
command: /bin/bash
stdin_open
: Keeps stdin open for Docker service
tty
: Allocates a pseudo-TTY for Docker service
restart
: Sets the restart policy for Docker container
Then you can run the following to get the container:
cd <directory of docker-compose.yaml>
docker compose up
Update the Labelling App Image
Any missed packages can be installed directly within the new container. Additionally, you have the option to utilize docker commit <container id> <image_name>:<tag>
to capture the changes made to the container and create a new image.
This ensures that future instances of the image will already include the newly installed packages
PyopenGL Issue
However, I met the same PyopenGL error when running labelling app inside the container, I refered to this blog to solve it. Thanks for those anonymous contributors a lot!
Lessons Learned: Overcoming Hurdles
Throughout this endeavor, several obstacles were encountered and addressed:
Fail1: Set up X11
Initially, I aimed to leverage the X11 GUI server to establish display connections between the container and the host server. This involved granting access to X11 and configuring display settings within the Docker container.
Despite these efforts, the attempt led to a frustrating error:
File "/usr/lib/python3.10/tkinter/__init__.py", line 2299, in __init__
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: couldn't connect to display ":1" ON CONTAINER
The steps I did are the following:
- Open the access to X11 to any user
ls -al /tmp/.X11-unix chmod a+r /tmp/.X11-unix/* xhost
- Mount the access
docker run -i -t --rm \
--net=host \
-v /tmp:/tmp \
--env DISPLAY=$DISPLAY \
--env XAUTHORITY=/tmp/.docker.xauth \
--name dairy-farm-dataset-linlin \
--mount src=/home/linlin/Workspace/01_FeedRunnerOfficial/dairy-farm-dataset,target=/dairy-farm-dataset,type=bind \
--mount src=/home/linlin/Dataset/01_FeedRunnerOfficial,target=/Dataset/01_FeedRunnerOfficial,type=bind \
dairy-farm-dataset bash
So I dig into how to solve it. When running Xorg
on hostmachine, I got:
/usr/lib/xorg/Xorg.wrap: Only console users are allowed to run the X server
When run gdm
, it raises error Only the root user can run GDM
It shows the current user has no permission to create a display, which requires root priviledge to operate. This may explain the fails. After that, I stopped this direction, then tried the xvfp
Fail2: Utilize xvfp
With reference to 3. Using x11vnc, I set up xvfp in a hostmachine with the following commands:
sudo apt-get install xvfb
Xvfb :99 -screen 0 1024x768x24 # set $DISPLAY from xvfb as :99
Then create a container by setting dislay =:99
, the one display port from xvfb
:
docker run -i -t --rm \
--net=host \
-v /tmp:/tmp \
--env DISPLAY=:99 \
--name dairy-farm-dataset-xvfb \
--mount src=/home/linlin/Workspace/01_FeedRunnerOfficial/dairy-farm-dataset,target=/dairy-farm-dataset,type=bind \
--mount src=/home/linlin/Dataset/01_FeedRunnerOfficial,target=/Dataset/01_FeedRunnerOfficial,type=bind \
dairy-farm-dataset bash
On the other hand, it only creates a virtual display, which requires a vnc or other software to display it. so sad.
That drives me to look into VNC directly.
Refer
- Use VNC to Set up GUI for container: https://github.com/bandi13/gui-docker
- Install OpenGL in Linux: https://blog.csdn.net/sinat_33896833/article/details/107362959
- Docker container gui applications: https://www.baeldung.com/linux/docker-container-gui-applications*