Using docker containers for a media server

  • by

Docker is a relatively new kid on the virtualization block. Rather than the age-old process of needing a hypervisor, guest OS, and one app per VM. We can use a host OS, install docker & docker-compose, and then deploy our services in containers (or micro-services).  Containers require less overhead, separation of application/OS, and the ability to update/manage containers without touching our host OS through services such as Portainer or Kubernetes.

Docker vs VM

Courtesy of Jenny Fong’s blog post.

Leveraging docker for home use

As you can see from the image above, this allows us to leverage a single VM to provide a multitude of services depending on the provisioned containers. In the docker-compose file provided below, I will leverage the services below:

  • Ouroboros – Keep containers up to date and restart once updated.
  • Plex – Media management
  • NZBGet –  USENET download application
  • Sonarr – TV series media management
  • Radarr – Movie media management
  • LetsEncrypt – SSL encryption with pre-configured NGINX reverse proxy configurations.

Example Docker-compose file:

version: '3'
services:

  ouroboros:
    container_name: ouroboros
    hostname: ouroboros
    image: pyouroboros/ouroboros
    environment:
      - CLEANUP=true
      - INTERVAL=300
      - LOG_LEVEL=info
      - SELF_UPDATE=true
      - LATEST=true
      - IGNORE=mongo influxdb postgres mariadb
      - TZ=America/Los_Angeles
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  plex:
    container_name: plex
    image: plexinc/pms-docker
    restart: unless-stopped
    environment:
      - TZ=America/Los_Angeles
      - PLEX_UID=1000
      - PLEX_GID=1000
      - PLEX_CLAIM=<XXXXXX REPLACE XXXXXXX>
    expose:
      - '32400/tcp'
    volumes:
      - /home/<insert_username>/plex/config:/config
      - /home/<insert_username>/tv:/data/tv
      - /home/<insert_username>/movies:/data/movies
      - /dev/shm:/transcode
    restart: unless-stopped

  nzbget:
    image: linuxserver/nzbget
    container_name: nzbget
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Americas/Los_Angeles
    volumes:
      - /home/<insert_username>/nzbget/config:/config
      - /home/<insert_username>/downloads:/downloads
      - /home/<insert_username>/temp:/localtemp
      - /dev/shm/nzbget:/ramdisk
    expose:
      - '6789/tcp'
    restart: unless-stopped
    depends_on:
      - letsencrypt

  sonarr:
    image: linuxserver/sonarr
    container_name: sonarr
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Americas/Los_Angeles
    volumes:
      - /home/<insert_username>/sonarr/config:/config
      - /home/<insert_username>/downloads:/downloads
      - /home/<insert_username>/temp:/blackhole
    expose:
      - '8989/tcp'
    restart: unless-stopped
    depends_on:
      - letsencrypt

  radarr:
    image: linuxserver/radarr
    container_name: radarr
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Americas/Los_Angeles
    volumes:
      - /home/<insert_username>/radarr/config:/config
      - /home/<insert_username>/downloads:/downloads
      - /home/<insert_username>/temp:/blackhole
    expose:
      - '7878/tcp'
    restart: unless-stopped
    depends_on:
      - letsencrypt

  letsencrypt:
    image: linuxserver/letsencrypt
    container_name: letsencrypt
    cap_add:
      - NET_ADMIN
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Americas/Los_Angeles
      - URL=<YOUR DOMAIN>
      - SUBDOMAINS=wildcard
      - VALIDATION=dns
      - DNSPLUGIN=cloudflare #optional
      - EMAIL=<YOUR EMAIL> #optional
      - DHLEVEL=2048 #optional
      - STAGING=false #optional
    volumes:
      - /home/<insert_username>/letsencrypt:/config
    ports:
      - 80:80
      - 443:443
    restart: unless-stopped

Important Note: If available leverage ‘/dev/shm’ or it’s equivalent as it acts as temporary storage within RAM. For instance, I used CentOS as my host OS and utilized ram storage for PLEX transcoding which greatly decreased my transcoding time. Please keep in mind you need a decent amount of RAM to leverage this feature.