Starting the erlang observer from within a docker container

I am currently working with elixir. It is a neat language, with a lot of good tooling. It’s rooted in the erlang world. A very useful tool to have some overview on the internals of the BEAM is the erlang observer.

Nowadays, the common workflow relies on containers. It is a very common issue to try to start graphical applications from within a container. Let’s prepare a playground

FROM elixir:1.10.4

ARG uid=1000
ARG gid=1000

RUN groupadd -g ${gid} alchymist \
    && useradd -u ${uid} -g alchymist alchymist \
    && mkdir -p /test \
 && chown alchymist:alchymist /test

USER alchymist
WORKDIR /test

ENTRYPOINT ["iex"]
CMD []

We can build it with

docker build --build-arg=uid=$(id -u) --build-arg=gid=$(id -g) -t alchymist:0 .

Let’s start normally

docker run --rm -ti alchymist:0

Trying to start the observer, we get an error

Erlang/OTP 22 [erts-10.7.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Interactive Elixir (1.10.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :observer.start()
09:46:02: Error: Unable to initialize GTK+, is DISPLAY set properly?
                                                                    {:error,
 {{:einval, 'Could not initiate graphics'},
  [
    {:wxe_server, :start, 1, [file: 'wxe_server.erl', line: 65]},
    {:wx, :new, 1, [file: 'wx.erl', line: 115]},
    {:observer_wx, :init, 1, [file: 'observer_wx.erl', line: 107]},
    {:wx_object, :init_it, 6, [file: 'wx_object.erl', line: 372]},
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
  ]}}
iex(2)>

The trick is to mount the needed files and pass the correct value for the environment variable DISPLAY.

docker run --rm \
    -v $HOME/.Xauthority:$HOME/.Xauthority:rw \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e DISPLAY=$DISPLAY \
    -ti alchymist:0

Starting the observer, we then succeed

Erlang/OTP 22 [erts-10.7.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Interactive Elixir (1.10.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :observer.start()
:ok
iex(2)>
the erlang observer started from a process inside a container
the erlang observer started from a process inside a container

Small tricks for large disks

Create a vmpool on an existing lvm logical volume

I have the very bad habit to create a volume group over which build the pool of
my main disk. Then I suddenly need a lvm pool for my virtual machines with libvirt.
I use this trick: I create a logical volume in the volume group, I place
another volume group inside the aforementioned logic volume and then I create
over it the lvm pool. In commands

% lsblk
sdb                         8:16   0   5.5T  0 disk  
└─sdb1                      8:17   0   5.5T  0 part  
  └─lvm                   254:1    0   5.5T  0 crypt 
    ├─vg-vms              254:2    0   600G  0 lvm   
    ├─vg-data             254:3    0   1.7T  0 lvm   
    ├─vg-Winzozz          254:4    0    30G  0 lvm   
    └─vg-shared           254:5    0     8G  0 lvm
% sudo lvcreate -l 100%FREE vg -n vmpool-me

% sudo vgcreate vmpool /dev/mapper/vg-vmpool--me

% lsblk
sdb                         8:16   0   5.5T  0 disk  
└─sdb1                      8:17   0   5.5T  0 part  
  └─lvm                   254:1    0   5.5T  0 crypt 
    ├─vg-vms              254:2    0   600G  0 lvm   
    ├─vg-data             254:3    0   1.7T  0 lvm   
    ├─vg-Winzozz          254:4    0    30G  0 lvm   
    ├─vg-shared           254:5    0     8G  0 lvm   
    └─vg-vmpool--me       254:6    0   3.1T  0 lvm

% sudo virsh

virsh # pool-define-as vmpool logical - - /dev/Terone/vmpool-me vmpool /dev/vmpool
Pool vmpool defined

virsh # pool-build vmpool
Pool vmpool built

virsh # pool-start vmpool
Pool vmpool started

Obviously, everything is inside a luks encrypted partition 😉