For years I’ve run a personal home server. Well scratch that, maybe I should call it a lab. I’ve been a long-term user of VSphere at home, and over the years I’ve slowly but surely expanded our environment to be more akin to a small business setup. It’s a hobby, and I enjoy it. Why not?
Recently while visiting r/homelab, I ran across a post about a guy who set up a linux host running docker all of his home media applications. Docker? What the heck is docker? Why do I need that when I can just spin-up VMs. Or how about a better question… Why do I need that when I can just install all of these apps in a single VM?
In short – here are the advantages:
- Less resource intensive than separate VMs. (Duh!)
- Complete environment isolation, meaning no more mono-libs or java libs cluttering up your host server.
- Speaking of Libs – having the RIGHT environment for the app you are running. What I need an OLD version of PHP to run this? No big deal!
- Separation of configuration data from application data.
- EASY upgrades
docker pull / docker run / docker rm
. Or my personal favorite… just script it! - Quick and easy deployment of new tools/toys to play with without causing harm to the rest of your system.
There are MANY other reasons to use docker, especially when it comes to development (both linux and web development). I won’t get into that here. Mostly logging this setup for myself. I’ll share after the break how I set up a brand new Ubuntu 16.04 VM with docker, and migrated my entire home media server to it in one night.
Before continuing – I always give credit where it’s due. Much of my inspiration came from this post [zackreed.me]. Check it out for more (likely better written) posts similar to this one!
Setting up your System
Install your base OS. In my case I used Ubuntu 16.04 LTS. Why Ubuntu? Well, I like it. I’ve used it long enough to not have to google-fu how to do the majority of configuration you need to get up and running.
Upgrade packages and system
sudo apt-get update sudo apt-get upgrade sudo apt-get dist-upgrade
Install NFS-Common for NFS Share Mounting. I use this to copy files back and forth to my NAS.
sudo apt-get install nfs-common
Update your NAS to accept secure connections from a specific IP. You can also do a username/password login, but I prefer to keep my fstab clean.
Update /etc/fstab to include your mountpoints
10.0.22.24:/volume1/tv /media/tv nfs rw,hard,intr 0 0 10.0.22.24:/volume1/movies /media/movies nfs rw,hard,intr 0 0 10.0.22.24:/volume1/downloads /media/downloads nfs rw,hard,intr 0 0
Install Docker
curl -fsSL https://get.docker.com/ | sh
New Docker Server Setup
mkdir -p /docker/containers/{couchpotato,muximux,nzbget,plex,plexpy,sonarr} chown -R user:user /docker mkdir -p /docker/downloads/{completed/Movies,completed/TV} mkdir -p /docker/containers/couchpotato/config mkdir -p /docker/containers/muximux/config mkdir -p /docker/containers/nzbget/config mkdir -p /docker/containers/plex/{config,transcode} mkdir -p /docker/containers/plexpy/config mkdir -p /docker/containers/sonarr/config
Install muximux
docker create \ --name=muximux \ -p 80:80 \ -p 443:443 \ -v /docker/containers/muximux/config:/config \ linuxserver/muximux
Create systemd startup script
vi /lib/systemd/system/muximux.service
Add this content
[Unit] Description=muximux container Requires=docker.service After=docker.service [Service] User=dencur Restart=on-failure RestartSec=45 ExecStart=/usr/bin/docker start -a muximux ExecStop=/usr/bin/docker stop -t 2 muximux [Install] WantedBy=multi-user.target
Enable on startup
systemctl enable muximux.service
If you want to start it up for testing
systemctl start muximux
Create the upgrade script
vi ~/bin/updatemuximux
Paste this into the script
#!/bin/bash # Define a timestamp function timestamp() { date +"%Y-%m-%d_%H-%M-%S" } timestamp echo "Pulling Latest from linuxserver/muximux" docker pull linuxserver/muximux echo "Stopping muximux Container" docker stop muximux echo "Backing up old muximux Container to muximux_$(timestamp)" docker rename muximux muximux_$(timestamp) echo "Creating and starting new muximux Server" docker create \ --name=muximux \ -p 80:80 \ -p 443:443 \ -v /docker/containers/muximux/config:/config \ linuxserver/muximux docker start muximux
Setup Plex
docker create \ --name=plex \ --net=host \ -e VERSION=latest \ -e PUID=1000 -e PGID=1000 \ -v /docker/containers/plex/config:/config \ -v /media/tv:/media/tv \ -v /media/movies:/media/movies \ linuxserver/plex
Rsync over the old plex server
rsync -vaE --exclude 'Cache' \ --progress \ /var/lib/plexmediaserver/Library/Application\ Support/Plex\ Media\ Server \ user@remoteserver:~/plexstuff/
Create systemd startup script
vi /lib/systemd/system/plex.service
Add this content
[Unit] Description=Plex container Requires=docker.service After=docker.service [Service] User=dencur Restart=on-failure RestartSec=45 ExecStart=/usr/bin/docker start -a plex ExecStop=/usr/bin/docker stop -t 2 plex [Install] WantedBy=multi-user.target
Enable on startup
systemctl enable plex.service
If you want to start it up for testing
systemctl start plex
Create the upgrade script
vi ~/bin/updateplex
Paste this into the script
#!/bin/bash # Define a timestamp function timestamp() { date +"%Y-%m-%d_%H-%M-%S" } timestamp echo "Pulling Latest from linuxserver/plex" docker pull linuxserver/plex echo "Stopping plex Container" docker stop plex echo "Backing up old plex Container to plex_$(timestamp)" docker rename plex plex_$(timestamp) echo "Creating and starting new plex Server" docker create \ --name=plex \ --net=host \ -e VERSION=latest \ -e PUID=1000 -e PGID=1000 \ -v /docker/containers/plex/config:/config \ -v /media/tv:/media/tv \ -v /media/movies:/media/movies \ linuxserver/plex docker start plex
Setup NZBGet
docker create \ --name nzbget \ -p 6789:6789 \ -e PUID=1000 -e PGID=1000 \ -v /docker/containers/nzbget/config:/config \ -v /media/downloads/complete:/downloads/complete \ -v /media/downloads/incomplete:/downloads/incomplete \ linuxserver/nzbget
Logged into the web portal and did a bunch of configuration stuff to point to the right folders.
Create systemd startup script
vi /lib/systemd/system/nzbget.service
Add this content
[Unit] Description=NZBGet container Requires=docker.service After=docker.service [Service] User=dencur Restart=on-failure RestartSec=45 ExecStart=/usr/bin/docker start -a nzbget ExecStop=/usr/bin/docker stop -t 2 nzbget [Install] WantedBy=multi-user.target
Enable on startup
systemctl enable nzbget.service
If you want to start it up for testing
systemctl start nzbget
Create the upgrade script
vi ~/bin/updatenzbget
Paste this into the script
#!/bin/bash # Define a timestamp function timestamp() { date +"%Y-%m-%d_%H-%M-%S" } timestamp echo "Pulling Latest from linuxserver/nzbget" docker pull linuxserver/nzbget echo "Stopping nzbget Container" docker stop nzbget echo "Backing up old nzbget Container to nzbget_$(timestamp)" docker rename nzbget nzbget_$(timestamp) echo "Creating and starting new nzbget Server" docker create \ --name nzbget \ -p 6789:6789 \ -e PUID=1000 -e PGID=1000 \ -v /docker/containers/nzbget/config:/config \ -v /media/downloads/complete:/downloads/complete \ -v /media/downloads/incomplete:/downloads/incomplete \ linuxserver/nzbget docker start nzbget
Setup Couch Potato
docker create \ --name=couchpotato \ -v /etc/localtime:/etc/localtime:ro \ -v /docker/containers/couchpotato/config:/config \ -v /media/downloads/complete/Movies:/downloads \ -v /media/movies:/movies \ -e PGID=1000 -e PUID=1000 \ -p 5050:5050 \ linuxserver/couchpotato
Create systemd startup script
vi /lib/systemd/system/couchpotato.service
Add this content
[Unit] Description=Couchpotato container Requires=docker.service After=docker.service [Service] User=dencur Restart=on-failure RestartSec=45 ExecStart=/usr/bin/docker start -a couchpotato ExecStop=/usr/bin/docker stop -t 2 couchpotato [Install] WantedBy=multi-user.target
Enable on startup
systemctl enable couchpotato.service
If you want to start it up for testing
systemctl start couchpotato
Create the upgrade script
vi ~/bin/updatecouchpotato
Paste this into the script
#!/bin/bash # Define a timestamp function timestamp() { date +"%Y-%m-%d_%H-%M-%S" } timestamp echo "Pulling Latest from linuxserver/couchpotato" docker pull linuxserver/couchpotato echo "Stopping CouchPotato Container" docker stop couchpotato echo "Backing up old CouchPotato Container to couchpotato_$(timestamp)" docker rename couchpotato couchpotato_$(timestamp) echo "Creating and starting new CouchPotato Server" docker create \ --name=couchpotato \ -v /etc/localtime:/etc/localtime:ro \ -v /docker/containers/couchpotato/config:/config \ -v /media/downloads/complete/Movies:/downloads \ -v /media/movies:/movies \ -e PGID=1000 -e PUID=1000 \ -p 5050:5050 \ linuxserver/couchpotato docker start couchpotato
Update Couchpotato notify from Preferences.xml Auth Token
Setup Sonarr
If you are moving Sonarr go to your current instance look up the General->Info, the bottom item is where the database is stored. Copy this folder into your /config folder before starting the VM
Sonarr docker
docker create \ --name sonarr \ -p 8989:8989 \ -e PUID=1000 -e PGID=1000 \ -v /dev/rtc:/dev/rtc:ro \ -v /docker/containers/sonarr/config:/config \ -v /media/tv:/media/tv \ -v /media/downloads/complete/tv:/downloads/complete/tv \ -v /media/downloads/complete/tv_manual:/downloads/complete/tv_manual \ linuxserver/sonarr
Create systemd startup script
vi /lib/systemd/system/sonarr.service
Add this content
[Unit] Description=Sonarr container Requires=docker.service After=docker.service [Service] User=dencur Restart=on-failure RestartSec=45 ExecStart=/usr/bin/docker start -a sonarr ExecStop=/usr/bin/docker stop -t 2 sonarr [Install] WantedBy=multi-user.target
Enable on startup
systemctl enable sonarr.service
If you want to start it up for testing
systemctl start sonarr
Create the upgrade script
vi ~/bin/updatesonarr
Paste this into the script
#!/bin/bash # Define a timestamp function timestamp() { date +"%Y-%m-%d_%H-%M-%S" } timestamp echo "Pulling Latest from linuxserver/sonarr" docker pull linuxserver/sonarr echo "Stopping sonarr Container" docker stop sonarr echo "Backing up old sonarr Container to sonarr_$(timestamp)" docker rename sonarr sonarr_$(timestamp) echo "Creating and starting new sonarr Server" docker create \ --name sonarr \ -p 8989:8989 \ -e PUID=1000 -e PGID=1000 \ -v /dev/rtc:/dev/rtc:ro \ -v /docker/containers/sonarr/config:/config \ -v /media/tv:/media/tv \ -v /media/downloads/complete/tv:/downloads/complete/tv \ -v /media/downloads/complete/tv_manual:/downloads/complete/tv_manual \ linuxserver/sonarr docker start sonarr
Install Plexpy
docker create \ --name=plexpy \ -v /etc/localtime:/etc/localtime:ro \ -v /docker/containers/plexpy/config:/config \ -v /docker/containers/plex/config/Library/Application\ Support/Plex\ Media\ Server/Logs:/logs:ro \ -e PGID=1000 -e PUID=1000 \ -p 8181:8181 \ linuxserver/plexpy
Create systemd startup script
vi /lib/systemd/system/plexpy.service
Add this content
[Unit] Description=Plexpy container Requires=docker.service After=docker.service [Service] User=dencur Restart=on-failure RestartSec=45 ExecStart=/usr/bin/docker start -a plexpy ExecStop=/usr/bin/docker stop -t 2 plexpy [Install] WantedBy=multi-user.target
Enable on startup
systemctl enable plexpy.service
If you want to start it up for testing
systemctl start plexpy
Create the upgrade script
vi ~/bin/updateplexpy
Paste this into the script
#!/bin/bash # Define a timestamp function timestamp() { date +"%Y-%m-%d_%H-%M-%S" } timestamp echo "Pulling Latest from linuxserver/plexpy" docker pull linuxserver/plexpy echo "Stopping plexpy Container" docker stop plexpy echo "Backing up old plex Container to plex_$(timestamp)" docker rename plexpy plexpy_$(timestamp) echo "Creating and starting new plexpy Server" docker create \ --name=plexpy \ -v /etc/localtime:/etc/localtime:ro \ -v /docker/containers/plexpy/config:/config \ -v /docker/containers/plex/config/Library/Application\ Support/Plex\ Media\ Server/Logs:/logs:ro \ -e PGID=1000 -e PUID=1000 \ -p 8181:8181 \ linuxserver/plexpy docker start plexpy
Enable Docker Sockets
I like to enable Docker sockets on my docker servers so I can use some 3rd party tools to monitor status. Admittedly I don’t use these often, but if you’re interested in accessing docker information from a tool like the Chrome App – Docker UI. Turn on the port access by doing the steps below.
Create a file called to make docker available on a TCP socket on port 2375:
vi /etc/systemd/system/docker-tcp.socket
[Unit] Description=Docker Socket for the API [Socket] ListenStream=2375 BindIPv6Only=both Service=docker.service [Install] WantedBy=sockets.target
Then enable this new socket:
systemctl enable docker-tcp.socket systemctl enable docker.socket systemctl stop docker systemctl start docker-tcp.socket systemctl start docker
Let me know how it goes!