Running GUI apps in Docker

Josip Maslać, TerminalZG, 01/2017

Me

  • Josip Maslać

  • (java) developer

  • average GNU/Linux user

  • cofounder and owner of

nabava logo sova sa tekstom nabava net

aplos.hr/posao.html

Java developers wanted!

Docker 101

  • open-source project that automates the deployment of applications inside software containers

container

virtual machines

Classic VMs

vm other

Docker

vm docker

lightweight & fast

Key terms

  • images

  • repositories

  • containers

  • image ⇒ template for a container

  • OOP analogy: classes & objects

Demo

$ docker pull ubuntu	# docker hub (hub.docker.com)
$ docker images	# list all images

REPOSITORY   TAG      IMAGE ID     CREATED      SIZE
nabava/solr  latest  a53291b74a7c  5 weeks ago  1.03 GB
nabava/mysql latest  b3a5e0cb42b3  5 weeks ago  718.5 MB
nabava/java  latest  05608501f34b  5 weeks ago  808.2 MB
ubuntu       latest  104bec311bcd  3 weeks ago  128.9 MB
$ docker images | grep ubuntu

REPOSITORY   TAG      IMAGE ID     CREATED      SIZE
ubuntu       latest   104bec311bcd 3 weeks ago  128.9 MB
ubuntu       16.04    104bec311bcd 3 weeks ago  128.9 MB
ubuntu       14.04.5  ac192759f936 3 months ago 187.9 MB

Running containers

# docker run <image> [command]
$ docker run ubuntu:16.04 echo "hello"
hello
$ docker ps	# list running containers

CONTAINER ID  IMAGE           COMMAND             CREATED     STATUS     PORTS                     NAMES
4802ebe8de68  nabava/haproxy  "bash /run.sh"      4 weeks ago Up 3 hours                           haproxy
03f60e3ba466  nabava/solr     "/bin/bash /run.sh" 5 weeks ago Up 4 hours                           solr
3a4c3321be1f  nabava/mysql    "/bin/bash run.sh"  5 weeks ago Up 4 hours 0.0.0.0:23306->3306/tcp   mysql
$ docker ps -a	# list all

CONTAINER ID  IMAGE           COMMAND             CREATED        STATUS                    PORTS                     NAMES
208651c624d5  ubuntu:16.04    "echo hello"        10 minutes ago Exited (0) 10 minutes ago                           naughty_lovelace
4802ebe8de68  nabava/haproxy  "bash /run.sh"      4 weeks ago    Up 3 hours                                          haproxy
03f60e3ba466  nabava/solr     "/bin/bash /run.sh" 5 weeks ago    Up 4 hours                                          solr
3a4c3321be1f  nabava/mysql    "/bin/bash run.sh"  5 weeks ago    Up 4 hours                0.0.0.0:23306->3306/tcp   mysql

container is alive if: ps ax | wc -l > 0

Creating images

$ docker run -it ubuntu /bin/bash
root@db66d65ad2e7:/# apt-get install apache2
root@db66d65ad2e7:/# apt-get install libapache2-mod-php
root@db66d65ad2e7:/# exit
$ docker ps -a

CONTAINER ID  IMAGE           COMMAND             CREATED     STATUS                   PORTS                    NAMES
db66d65ad2e7  ubuntu          "/bin/bash"         3 hours ago Exited (1) 3 hours ago                            jovial_pike
$ docker commit <container_id> <image_name>

Creating images

Dockerfile

FROM ubuntu:16.04
MAINTAINER Josip Maslac <josip.maslac@nabava.net>

RUN apt-get update

RUN apt-get -y apache2
RUN apt-get -y libapache2-mod-php
ADD configuration /etc/myconfiguration

CMD ["/usr/sbin/apache2", "-DFOREGROUND"]
$ docker build -t <image_name> .
$ docker push <image_name>

Recap

docker image vs containers

One more thing

container volumes

$ docker run -v /home/developer/mysql-data:/var/lib/mysql mysql

-v <host_folder>:<container_folder>

Running GUI apps in docker

  • X Windows System (X11)

    • basic framework for a GUI environment

    • client-server

      • localhost (unix socket)

      • network

  • X server

    • sends graphics resources and keyboard/mouse events to X clients

X server architecture

x client server

Firefox

$ docker run -it ubuntu /bin/bash
root@7692a32340ca:/# apt-get install firefox
root@7692a32340ca:/# exit
$ docker commit 7692 firefox

Firefox

key part: /tmp/.X11-unix

live demo…​

$ docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix firefox /bin/bash
root@208651c624d5:/# firefox
Error: GDK_BACKEND does not match available displays
root@208651c624d5:/# exit

$DISPLAY env variable

$ docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix firefox /bin/bash
root@208651c624d5:/# firefox
Couldnt open libGL.so.1: libGL.so.1: cannot open shared object file: No such file or directory
root@208651c624d5:/# apt-get install libglu1-mesa
root@208651c624d5:/# exit
$ docker commit 208651c624d5 firefox

Firefox

$ docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix firefox /bin/bash
root@208651c624d5:/# firefox
No protocol specified
Failed to connect to Mir: Failed to connect to server socket: No such file or directory
Unable to init server: Could not connect: Connection refused
Error: cannot open display: :0
xhost +local:docker	# enable local docker containers to access X server

Recap

  • xhost +local:docker

  • -v /tmp/.X11-unix:/tmp/.X11-unix

  • -e DISPLAY=$DISPLAY

My goal

./dev_env.sh developer_private_key
# dev_env.sh - something like:

docker login our.private.repo
docker run mysql
docker run some_service
docker run some_other_service
docker run webapp

Context

  • in a non java world

    docker run -v /home/developer/app:/srv/www/htdocs php-webapp
  • use text editor for /home/developer/app

  • Java world:

    • Application containers (tomcat)

      • where your compiled (java) apps are running

    • IDEs (Eclipse)

      • tightly integrated with app containers

        • managing (start/stop, configure) && debugging

Possible solution

connect remotely to tomcat

eclipse tomcat remote

other stuff in our tomcat container (html2pdf, custom fonts etc.)

development environment <> production

(Our) solution

eclipse image

on top of tomcat image

eclipse in docker
$ docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix eclipse

Gotchas

process owner

$ docker run -it ubuntu whoami
root

Gotchas

  • file ownership & permissions

docker run -it -v /home/user/workspace:/workspace ... eclipse
# on the host
$ ls -ls /home/user
...
drwxr-xr-x  5 root  root  4096 Sij  3 12:28 workspace
...

Workaround

# Dockerfile - container entry script:
...
CMD ["/bin/bash","/run.sh"]
# run.sh - initializes things:

groupadd -g $DEV_GROUP_ID users
useradd -g $DEV_GROUP_ID -u $DEV_USER_ID developer
...
chown -R developer:users /workspace
...
exec gosu developer eclipse/./eclipse -data /home/developer/workspace
# container start script
DEV_GROUP_ID=$( id -g )
DEV_USER_ID=$( id -u )

docker run -e DEV_GROUP_ID -e DEV_USER_ID ... eclipse

Gotchas

  • pasting

    • text - yes

    • files - no go

  • no "external" tools available

    • other then those installed in image/container

  • you cannot get "out of" a container

Alternatives

  • ssh + X11 forwarding (-X switch)

  • VNC

    • full desktop installed inside container

Windows?

doable!

  • Xming X Server for Windows

  • running ssh daemon inside a container

    • exposed on some port

  • putty to that container

    • ("X11 forwarding" checked)

    • start you GUI app

Windows

docker eclipse windows

Conclusion

  • minimum dev. environment setup time

  • dev = production

    • not 100% but close enough

  • learned someting new

    • and now talking about it

Thank you