HomeLab initial setup
Installing Docker
There is no point in explaining in details how to install docker on your machine as the documentation would be deprecated the moment I finish this sentence.
However you can find how to install Docker on Ubuntu right here.
Installing Docker-compose
Now that you have installed Docker, you can install docker-compose
, a magnificent tool to configure your container with a simple text file !
The instructions can be found on docker’s official documentation.
Setting up the docker network
We want each of our docker container to have statics MAC and IP addresses. To do so, we use the macvlan
network mode.
To be able to use this mode, we first need to create the actual macvlan.
Let’s create a script called host-macvlan-net.sh
containing the command and its explanation :
vim host-macvlan-net.sh
Here is the script content:
#!/bin/zsh
# This script creates the network host-macvlan-net used by the docker containers on this server
# Every container has an address in 10.0.6.x
# Note that it is impossible for the current server to ping these containers
# However an external computer, or another docker container will be able to do so
docker network create -d macvlan --subnet=10.0.0.0/20 --gateway=10.0.0.1 --ip-range=10.0.6.0/24 -o parent=eno1 host-macvlan-net
# Use `docker network ls` to list the docker networks
# Use `docker network inspect host-macvlan-net` to print the network details
# User `docker network rm host-macvlan-net` to remove the network
The command is
docker network create -d macvlan --subnet=10.0.0.0/20 --gateway=10.0.0.1 --ip-range=10.0.6.0/24 -o parent=eno1 host-macvlan-net
-d macvlan
: uses the network modemacvlan
--subnet=10.0.0.0/20
: defines the subnet for the network--gateway=10.0.0.1
: defines the gateway for the network--ip-range=10.0.6.0/24
: defines the ip-range for the network (useful only if you don’t want to set static IPs in the docker-compose file)-o parent=eno1
: defines the parent interface (here it is my ethernet interface)host-macvlan-net
: the name I gave to the network.
We can now use docker network ls
to list the docker networks to verify that it was properly created.
Setting up an application
Since most applications will be set up the same way, I decided I would show in details how a simple one is done here to save some effort for the next ones.
In this sample application setup we install pyload.
The folder
I like to organize my applications in folders :
braincoke@nuc$ ls -1
Firefly
Gitlab
Jdownloader2
MayanEdms
Monica
OpenHab
Organizr
Portainer
Pyload
Rancher
Torrent
Each folder here will contain :
- the docker-compose.yml file describing the application
- the directories that will be mounted in the container
The network
Since I decided at the beginning of my project that each container will have its own reserved IP address, I will have to manually reserve the IP address in my router configuration panel.
If I decide that the IP address of the container should be 10.0.6.11
, I know that the MAC address will be 02:42:0A:00:06:0B
.
With that information I can set my DHCP to reserve the IP 10.0.6.11
to the MAC address 02:42:0A:00:06:0B
.
Docker MAC addresses are predictable for static IPs. It will follow the format : 02:42:<IPv4 address in hexa>
. For instance 10
in hexadecimal is 0A
, 11
is 0B
and 6
is 06
.
The docker-compose file
Once we have our folder (that was hard), we have to create our docker-compose.yml file.
cd Pyload
touch docker-compose.yml
Our docker-compose will look like this :
version: '2.2'
services:
web:
container_name: 'pyload'
image: 'writl/pyload:latest'
hostname: 'pyload'
restart: unless-stopped
environment:
- PUID=1000
- PGID=1004
ports:
- '80:80'
- '443:443'
volumes:
- '../NAS/Downloads:/opt/pyload/Downloads'
- './config:/opt/pyload/pyload-config'
networks:
host-macvlan-net:
ipv4_address: 10.0.6.11
networks:
host-macvlan-net:
external:
name: host-macvlan-net
As you can see from the line image: 'writl/pyload:latest'
, we are downloading a container named pyload
with the tag latest
from user writl
from hub.docker.io.
Be very careful what container you download from hub.docker.io. It is as dangerous as downloading an unkwnown binary and executing it on your system. Take 10 minutes to overview the Dockerfile and see if there is something shady going on when the image is being built.
Here is a brief explanation of most of the configuration lines :
version: '2.2'
: the docker-compose file version used (expands or reduces the scope of options that can be used in the file)services
: we tell the file that we are about to describe containersweb
: this is our first service, we call it “web”container_name
: the name we want our container to have. Used by the docker daemon.hostname
: the name our container will give itself on the network.restart
: define when to restart the containerenvironment
: define environment variablesports
: define ports you want to exportvolumes
: define volume you want to mount from the system to the containernetworks
: tell the file we are about to define the network configuration for the containerhost-macvlan-net
: tell the file we are about to define the configuration for the network namedhost-macvlan-net
ipv4_address
: the IP address we want our container to have
networks
: describe the networks we will use for our container
When using the volumes
option, remember that the syntax is <path/to/local/dir>:<path/to/dir/inside/container>
.
To summarize all of this, our docker file is saying that :
- our container comes from the docker hub
- our container will be named
pyload
- the hostname of the container will also be
pyload
- its IP address will be
10.0.6.11
- the
PUID
andGUID
environment variables will be set to our predefined values in the container - some volumes will be mounted as described in the file
Mount points
Creating the directories
As we have seen from our docker-compose file, we have specified that :
- the directory
../NAS/Downloads
should be mounted to/opt/pyload/Downloads
inside the container - the directory
./config
should be mounted to/opt/pyload/pyload-config
inside the container
We don’t have to create the directories inside the containers, docker will handle that (if they don’t already exist). However we do need to create them on our system. So be sure that ~/NAS/Downloads
and ~/Pyload/config
exist before starting the container !
You will often see a mount point ./config
. This is a really usefull way to save the application config. Docker containers are stateless, when a container is removed, all the data it contained is destroyed… unless it was stored in a mounted directory !
By mounting the application config folder, you can save the state of your docker container and back it up regularly if you ever have a hardware issue with your homelab server.
Docker volumes
You can also obtain data persistence by creating docker volumes which is the recommended way to mount volumes.
This creates a data blob that you can reuse in other containers and is managed by docker. It adds a layer of security since the container does not have direct access to the host filesystem.
Using a NAS
In my setup I mostly use a NAS to store :
- the backups of the configuration directories
- the container downloads
To do so I mount the NAS directory directly on the host.
For instance if I need to mount the NAS directory //nas/Downloads
to the host ~/mounted/Downloads/
I will need to :
- Create a user
downloaduser
with the correct rights on the NAS. - Create a read-only file
/etc/nas-downloaduser-credentials
containing thedownloaduser
credentials. - Add the following line to
/etc/fstab
://nas/Download /home/braincoke/mounted/Downloads cifs user,rw,credentials=/etc/nas-downloaduser-credentials,dir_mode=0777,file_mode=0777,iocharset=utf8,x-systemd.automount,vers=3.0 0 0
The file /etc/nas-downloaduser-credentials
looks like this :
username=downloaduser
password=horse-staple-battery-correct-vintage
We change its permission to read-only to the user with chmod 400 /etc/nas-downloaduser-credentials
.
Since the credentials are not protected on the host, it is important to reduce its privileges on the NAS to the strict minimum.
Managing your containers
Once you have your docker-compose.yml
file, you can start the container with :
docker-compose up -d
-d
starts the process as a daemon. Also, you must do it in the directory
containing the file or use the appropriate option to specify which docker-compose
file should be used.
If you ever need to see the container logs, just run :
docker-compose logs -f
To stop all the containers started by the file:
docker-compose stop
Replace stop
by restart
to restart the containers.
And replace stop
by rm
to delete the containers.
You can list the running containers with docker ps
and all the containers (including the stopped ones) wit docker ps -a
.
Backup script
I always end up my configurations by creating a backup script and testing my backup.
If you have never tested your backup, consider you have none.
I store my backup scripts in ~/scripts/backup
and the backup themselves in ~/backup
which is a mounted volume from my NAS.
That way, my backup are stored on another device.
The purpose of the backup script is to back up the state of the container. To do so, I copy and tar every volume the container mounts.
Conclusion
This post exposed the basics of how I manage my docker-compose files, volumes, and backups. The next posts will explain briefly how to install specific applications and how to configure them.