Running Jellyfin in a Docker container

This post is a bit of a departure. I’m mixing work with a hobby. The hobby is expanding my media network and the work is a better understanding of good ways to persist data in Docker containers.

While waiting for the arrival of ATSC 3.0 (aka “NextGen TV”) in Boston, I funded a Kickstarter for Silicon Dust’s ATSC 3.0 network tuner (which also tunes ATSC 1.0 broadcasts). The HDHomeRun HDHR5-4K comes with DVR and tuner software which is pretty good. But I also wanted to see what else would work with the system. While reading Silicon Dust’s forums, I came across the open source Jellyfin media server.

I run a Windows Server 2019 Hyper-V environment which can directly support Linux Docker containers. But because I had previously built an Ubuntu VM in Hyper-V, I decided to run the Jellyfin container there. Interestingly, the Jellyfin server is itself built on .Net Core 3.1. You may wonder why I didn’t just containerize the app into a Windows container and run it directly on Hyper-V. That’s a good question. I guess I took the easy way out because Jellyfin comes all ready to go as a Linux container. There are better ways to run Linux containers in Windows Server than using a full Linus distro, like LinuxKit. But for my purposes, using my Ubuntu VM is fine. It ends up looking like this:

Running Jellyfin in a Docker container on Windows with Hyper-V
Running Jellyfin in a Docker container on Windows with Hyper-V (click to enlarge)

You can search the net for help installing Docker on Ubuntu and then retrieving the Jellyfin container from the catalog. What interested me is the question of how to run Jellyfin in a container that could be thrown away and replaced when updates happen without losing the container’s state.

Jellyfin can use the HDHomeRun tuners for its DVR features. I also wanted to be able to point a current or future Jellyfin library to content stored anywhere outside the container. For example, I wanted the Jellyfin Docker container to be able to access the VM’s filesystem and a NAS on my network. And, I didn’t want to have to reset settings like TLS ports each time the container is replaced. All those requirements meant Jellyfin libraries that store content and Jellyfin configuration settings would have to be stored outside the container to be persistent. And the Docker container would need to be configured to permit these accesses.

It turned out to be pretty simple to do. You only need to use Docker bind mounts to map explicit paths from the Ubuntu host to the Docker container. The doc seems to disapprove of bind mounts but I think they work great for this kind of application. You can also use a bind mount to mount a volume in the container that is remote to the Ubuntu host. That volume has to exist as a mount point in the Ubuntu host before it can be mapped. For network volumes, just make sure to mount those volumes to the VM at boot time in fstab.

A docker-compose.yml file is the most convenient way to map the Jellyfin configuration file volumes and Jellyfin content library volumes to the Docker container. Here’s my file:

version: "3"
services:
  jellyfin:
    container_name: "jellyfin"
    image: jellyfin/jellyfin
    user: 1000:998
    network_mode: "host"
    restart: "unless-stopped"
    environment:
      - JELLYFIN_CACHE_DIR=/var/cache/jellyfin
      - JELLYFIN_CONFIG_DIR=/etc/jellyfin
      - JELLYFIN_DATA_DIR=/var/lib/jellyfin
      - JELLYFIN_LOG_DIR=/var/log/jellyfin
    volumes:
      - /jellyfin/etc:/etc/jellyfin
      - /jellyfin/cache:/var/cache/jellyfin
      - /jellyfin/lib:/var/lib/jellyfin
      - /jellyfin/log:/var/log/jellyfin
      - /jellyfin/media:/var/jellyfin/media
      - /air11nas:/var/jellyfin/air11nas

Note that /air11nas is an NAS share, mounted in fstab like this:

//air11nas/media/jellyfin  /air11nas  cifs  username=YOURNASUSERNAME,password=USERNAMEPASSWORD,iocharset=utf8  0  0

You may think it a bit of a kludge, but it works great. I have issued docker container rm jellyfin multiple times, launched a new instance of the Jellyfin container and everything is right where it should be. And, as you can see in the screenshot below, I can use the HDHomeRun with Jellyfin to record shows and never worry about having to individually erase them. Since DVR recordings are in the container, they disappear when the container does. OTOH, anything I want to save or persist I simply move to the NAS.

Persistent and temporary Jellyfin content in a library in a Docker container.
Persistent and temporary Jellyfin content in a library (click to enlarge)

It was fun to configure Jellyfin in a container inside an Ubuntu VM on Windows. Try it! You’ll like it.


Posted

in

,

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *