How to run Tvheadend Server using Docker

Firstly before we begin i should highlight the fact that there is already a Tvheadend Server (and client) Kodi Addon created by the CoreELEC team, so if you aren’t interested in Docker then please use the Addon instead.

With that out of the way let’s list the reason why we might want to run Tvheadend Server as a Docker container:-

Control over version - You can dictate the version of Tvheadend you want, if you want latest stable, you can do that, if you want older builds, you can do that, if you want bleeding edge master commits, you can also do that, the choice is yours :-).

Platform and architecture agnostic - If you can install Docker on your host then you can run Tvheadend Server, the only pre-req is the Docker engine. What this means is you can move your Tvheadend config from different OS’s and even different Architectures without any loss of config, which is awesome!.

Step 1. So as mentioned above the first step is to get Docker installed, this can be done via the CoreELEC maintained Docker addon, to install it simply do a search for ‘docker’, and install. Once it’s installed you can confirm its working by SSHing into your host and then issue the command ‘docker info’.

Step 2. Decide which version of Tvheadend you want to run, this is best explained by clicking on the link below and going to the ‘Version Tags’ section:-

If you want to run a specific build then you can see the full list of all available tagged Docker images here:-
https://hub.docker.com/r/linuxserver/tvheadend/tags

Step 3. Now we know which version we want to run, we now need to create the Docker Container, this is done via the command line, so SSH in to your host and issue the following:-

mkdir -p /storage/.user/docker/config/tvheadend && \
docker run -d \
  --name=tvheadend \
  --restart unless-stopped \
  --device /dev/dvb:/dev/dvb \
  -e PUID=0 \
  -e PGID=0 \
  -e TZ=Europe/London \
  -p 9981:9981 \
  -p 9982:9982 \
  -v /storage/.user/docker/config/tvheadend:/config \
  -v /var/media/External/TV:/data \
  linuxserver/tvheadend:release-4.2

Replacing any paths with appropriate values and the version you wish to run.

Step 4. You may find that the container actually starts before all TV tuners are detected and available, in order to work around this i have created a simple script to help with this scenario:-

#!/bin/bash

# script designed to make the starting of docker containers (particularly tvheadend)
# a little bit more robust, as detection of dvb adapters can be slow and thus cause
# a timeout and failure for the container to start.

docker_path="/storage/.kodi/addons/service.system.docker/bin/docker"

dvb_adapter_count=4

# wait for docker to be responsive
while [ $(systemctl is-active docker) != "active" ]; do
        sleep 0.1s
done

# wait for dvb adapters to be present
while [ ! -d "/dev/dvb" ]; do
        sleep 0.1s
done

# if number of adapters is less than the expected max amount (4) then we sleep to allow 
# all available to be detected before starting the container.
if [ $(find /dev/dvb -mindepth 1 -maxdepth 1 -type d | wc -l) != "${dvb_adapter_count}" ]; then
        sleep 10s
fi

# set container to auto restart (will cause it to auto start on boot) and then force
# start.
"${docker_path}" update --restart=always tvheadend ; "${docker_path}" start tvheadend

In order for the above script to auto run you need to call it from the auto start script, this is located at ‘/storage/.config/autostart.sh’, it may or may not exist, if it doesnt exist then create it as follows, else append the call line to the existing script:-

#!/bin/bash

# script to wait for all adapters to be present before running container
/storage/<name of the script above>

Step 5. So how you do you keep your Docker images up to date with any new releases you may be asking, this is achieved by using another Docker image which includes an application called ‘Watchtower’.
What this application does is it monitors ‘Docker Hub’ for changes, if a change is detected (as in a new image is built) then Watchtower will automatically pull the image down, stop and delete the existing container, and then re-create the container with the existing parameters.

To get Watchtower installed you simply perform the following, again from SSH on the host:-

mkdir -p /storage/.user/docker/config/watchtower && \
docker run -d \
  --name=watchtower \
  --restart unless-stopped \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e WATCHTOWER_NOTIFICATIONS=email \
  -e WATCHTOWER_NOTIFICATION_EMAIL_FROM=watchtower@gmail.com \
  -e WATCHTOWER_NOTIFICATION_EMAIL_TO=fred.blogs@gmail.com \
  -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.gmail.com \
  -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=fred.blogs@gmail.com \
  -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=mypassword \
  containrrr/watchtower:arm64v8-0.3.3 --debug --interval 43200

Again replacing any paths, version and email details (if you want it to notify you of updates).

Please note you will see ‘docker pull’ notifications in kodi due to the Docker addon notifications, so please keep the --interval value to a reasonably high number or you will be bombarded with notifications.

4 Likes

Thanks for the guide.

About step 4, where and how to put the script to work?

@binhex thanks a lot for this guide. It worked out for me. However, the usb dvb tuner is not detected. Any ideas?

The device is there but it can’t be accessed.

2019-08-01 10:58:47.142 [ ERROR] linuxdvb: unable to open /dev/dvb/adapter0/frontend0

you can put it anywhere on /storage/ and then simply call that script from the auto startup script located in /storage/,config/autostart.sh (if this file doesnt exist then create it).

p.s. please make sure you chmod +x all scripts you create.

edit - added to guide at step 4.

1 Like

so you can see the tuner is available on the host (as in not the container) right?, so ls -al /dev/dvb/ shows the adapter?

Yes I can see it. It is owned by root, might this cause problems?

I do have a Sundtek USB DVB tuner. Maybe the problem is there…

nope that shouldnt be a problem, as this container will run as root, as defined by PUID and PGID.

try restarting the container, it could be the issue i mentioned in step 4. where the container is up before the adapter is detected.

It is working now. It was kind of tricky with the sundtek drivers.

However, I’m on the latest TVH 4.3 now and I’m a little bit dissapointed by the channel switching times. How is your experience? Is it the docker container itself that might slow TVH down (I guess no)? Or is it the 4.3 version of TVH?

can you detail what the tricky bit was, i can add it to the guide then.

the experience with channel switching is a bit slow i admit, you can try the pre-channel switching option (cant remember the name of it but its on the tvh client), that drastically improved things but does mean you are using more tuners. as for docker slowing things down, in my experience docker is extremely good at performing at near bare metal speeds, so i doubt its docker.

A very useful thread.

As a possible alternative to TVH, it seems that there is now a docker build of NextPVR, as discussed here and here.

1 Like

–device /dev/dvb was the only one that worked for people who used our tuner with docker.

I have also seen --device /dev/drb:/dev/dvb etc. in customer setups which I guess should be a typo. All those different setups are confusing users…

/dev/drb see:

this is absolutely not working in most cases. Maybe some docker versions do not support that option.

so why do it difficult, just use --device /dev/dvb

/dev/dri is a different device completely, taken from the linuxserver github readme:-

--device /dev/dri	Only needed if you want to use your AMD/Intel GPU for hardware accelerated video encoding (vaapi).

--device /dev/dvb	Only needed if you want to pass through a DVB card to the container. If you use IPTV or HDHomeRun you can leave it out.

so both options are valid, i dont see any issues with the above personally, in my guide above i have only included an example of passing through /dev/dvb

i try “lsioarmhf/tvheadend” every thing work (built in tuner (–device=/dev/dvb) & Satip (–net=bridge ) )

but return to old 4.2 … it faster work thin 4.3