During add-on development I use Kodi installed on my operating system for testing. But what if I need to test my changes on various Kodi versions? It’s not so easy to install different versions of a package on such distros as Ubuntu. We could try some Kodi container image but I decided to build my own.

Existing Kodi container images

Before I started working on my Kodi container image I checked what other people did in this area.

docker.io/linuxserver/kodi-headless

This image has patched Kodi in order to run it without graphical user interface. The README has this description “most useful for a mysql setup of kodi to allow library updates to be sent without the need for a player system to be permanently on”. Despite on its advantages this image doesn’t fully fits to my needs. If you develop an add-on with UI you would also like see how the elements are displayed in Kodi.

docker.io/erichough/kodi

This one has completely different purpose. The goal is to provide containerized Kodi with full support of audio and video. It requires x11docker to be installed on the host in order to forward streams from the container to the host. docker.io/erichough/kodi doesn’t fit my needs as well. I don’t need support of audio and video playback and I don’t want to install any dependencies other than docker or podman.

I think these two images are the most popular in the Docker Hub and they either don’t missing GUI or have redundant dependencies. That’s why I decided to create my own Kodi container image.

Conkodi

I need a minimalistic container image with Kodi that is able to display GUI without audio and video playback capabilities. After several attempts I came to this dockerfile:

# Team Kodi officially supports ppa for Ubuntu
FROM ubuntu:20.04

# Packages installation should be unattended
ARG DEBIAN_FRONTEND=noninteractive
# YOu can specify a version of Kodi to install as build arg
ARG KODI_VERSION=18.9

# This needed for running VNC
ENV DISPLAY=:99 

# Adding ppa and install dependencies
RUN apt update && \
    apt install -y --no-install-recommends software-properties-common && \
    add-apt-repository -y ppa:team-xbmc/ppa && \
    apt -y purge openssl software-properties-common && \
    apt install -y --no-install-recommends dumb-init \
                                           # Without pulseaudio Kodi logs are unreadble and useless
                                           pulseaudio \
                                           # This needs for establishing SSL connections 
                                           ca-certificates \
                                           # Tigervnc implements an X server and provides VNC access
                                           tigervnc-standalone-server \
                                           tigervnc-xorg-extension \
                                           kodi=2:${KODI_VERSION}+* && \
    apt -y --purge autoremove

COPY start.sh /
COPY guisettings.xml /home/kodi/.kodi/userdata/guisettings.xml

# Various permission tweaks
RUN chmod +x /start.sh && \
    touch /home/kodi/.Xauthority && \
    chgrp -R 0 /home/kodi/ && \
    chmod -R g=u /home/kodi/

WORKDIR /home/kodi

# VNC port
EXPOSE 5999
# HTTP port
EXPOSE 8080
# EventServer port
EXPOSE 9777/udp

# It always a good practice to run applications in the container under some user
USER 1001
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["/start.sh"]

And here the starting script:

#!/bin/sh

pulseaudio > /dev/null 2>&1 &

vncserver $DISPLAY -noxstartup \
                   -securitytypes none \
                   -geometry 1600x900 \
                   # kodi doesn't start on lower depth values
                   -depth 24 \
                   -alwaysshared > /dev/null 2>&1 &

/usr/lib/x86_64-linux-gnu/kodi/kodi.bin --standalone  > /dev/null 2>&1 &

# Kodi starts with some delay
while [ ! -f ".kodi/temp/kodi.log" ]; do
    sleep 0.1
done

# Show kodi.log to the container's stdout
tail -f .kodi/temp/kodi.log

Troubles

Bit depth

Let me share the troubles I faced during development of Conkodi. In the beginning Kodi wasn’t able to start. It crashed immediately with the error message Failed to find matching visual. Here I should say that I started the vnc server in this way:

vncserver $DISPLAY -noxstartup \
                   -securitytypes none \
                   -geometry 1600x900 \
                   -depth 16 \
                   -alwaysshared > /dev/null 2>&1 &

I usually use -depth 16 in order to reduce resources consumption but apparently Kodi just doesn’t start if the bit depth lower 24. I had to look into Kodi sources to find root cause of the crash. I searched the string Failed to find matching visual and found one mention here. I found GetVisual() method in xbmc/windowing/X11/WinSystemX11GLContext.cpp:

XVisualInfo* CWinSystemX11GLContext::GetVisual()
{
  int count = 0;
  XVisualInfo vTemplate;
  XVisualInfo *visual = nullptr;

  int vMask = VisualScreenMask | VisualDepthMask | VisualClassMask;

  vTemplate.screen = m_screen;
  vTemplate.depth = 24;
  vTemplate.c_class = TrueColor;

  visual = XGetVisualInfo(m_dpy, vMask, &vTemplate, &count);

  if (!visual)
  {
    vTemplate.depth = 30;
    visual = XGetVisualInfo(m_dpy, vMask, &vTemplate, &count);
  }

  return visual;
}

Aha, perhaps vTemplate.depth = 24; means that Kodi expects that the bit depth equals 24. I changed the argument for vncserver and Kodi started.

Kodi logs

Another problem was Kodi logs. After starting the only thing I could see in the logs was:

ERROR: CActiveAESink::OpenSink - no sink was returned

I wanted to have as minimal image as possible and I didn’t include pulseaudio that caused this error. Having readable Kodi logs was one of my requirements therefore I added pulseaudio as well.

Volume mounts permissions

Last problem was to set the correct permission for mounted volumes. I found that the container runs with umask 0022 it means new files are created with mode 644 and directories are created with 755. This permissions don’t allow to delete files under host user in mounted directories. I needed to increase the privileges with sudo. Fortunately, podman has a cool feature to run containers with a certain umask value:

podman run -it --umask=0002 --volume=/some/dir:/mnt quay.io/quarck/conkodi:18

Building

If you want build the image locally just clone the repo and use your favorite container engine tool. I prefer podman and buildah:

git clone https://github.com/quarckster/conkodi.git
buildah bud --build-arg=<version of Kodi> -t conkodi:<version of Kodi> -f conkodi/stable.Dockerfile conkodi

You can also build an image with nightly version of Kodi:

buildah bud -t conkodi -f conkodi/nightly.Dockerfile conkodi

Prebuilt images

I have prebuilt some images and pushed them quay.io registry. You can find list of tags in https://quay.io/repository/quarck/conkodi?tab=tags

Usage

Just use the following command:

podman run -it --name kodi --rm -p 5999:5999 -p 8080:8080 -p 9777:9777/udp quay.io/quarck/conkodi:18

You can access Kodi GUI using any VNC client, e.g.:

krdc vnc://127.0.0.1:5999

References:

Discuss on Github