Monitoring Linux servers & Cisco switches using Zabbix in Docker via SNMP — Part 1 of 2
I had to set this up for work and could not find an all-in-one tutorial for it, so I’m hoping this write-up benefits somebody else. Do let me know if I missed anything, or of any suggestions of improvements — this is my first attempt at Docker.
This tutorial is not so much about Zabbix itself as it is about getting containerised Zabbix up and running so you can start using it. Note that you can use Zabbix without Docker, but this tutorial does deal with the containerised version.
Table of Contents
1.2 — …by setting the right permissions
2.0 — Container #2: Zabbix server
3.0 — Container #3: Zabbix web interface
Start with:
- A Linux server for hosting Zabbix (Ubuntu, at my workplace)
- Docker installed on said server (Ubuntu instructions here, or the script that I use: GitHub)
I’ll do this by giving you the script I used to spin up Zabbix and then walk you through it: GitHub. Note that I run my scripts with root privileges, which is necessary for Docker anyway.
Zabbix needs 3 containers:
- A database (this tutorial uses MySQL)
- The Zabbix server itself (this tutorial uses the MySQL variant)
- The Zabbix web interface (this tutorial uses the Apache variant)
i.e. the 3 sets of docker run
commands in the script.
There is a Zabbix server variant for use with PostgreSQL and there are Zabbix web interface variants in Apache and Nginx for each of those databases! Depending on your cup of tea, these other variants are on the Zabbix Docker Hub.
1.0 — Container #1: MySQL
LINE 1–4 avoids hardcoding passwords in plaintext in scripts / exposing passwords passed as arguments in ~/.bash_history
!
LINE 6 creates a directory for “persisting” data, as explained in 1.1 below.
LINE 7 sets permissions to allow data to be written to said directory, for reasons explained in 1.2 below.
LINE 9 creates a “network” in Docker so the 3 containers can actually talk to each other — one of the reasons for containerisation is isolation to begin with!
LINE 11–21 starts the MySQL container:
--name
is not just a placeholder — later containers reference it.- The
-e
flags configure the username(s) and password(s) for the MySQL database, among other options (see Environment Variables on the MySQL Docker Hub).MYSQL_ROOT_PASSWORD
is the only mandatory variable, if you are so inclined. --network
specifies the Docker “network” to join.- The
-v
flag “persists”data, as explained in 1.1 below. --restart
specifies the “restart policy” i.e. the container’s behaviour on exit.- The
-d
flag runs containers in “detached” mode (“backgrounds” it), otherwise the first container will “take over” your terminal after it is spun up! - The last few options (lines 20 & 21) come from the Zabbix documentation. The Zabbix server container will fail to start if these are left out.
1.1 — How to persist data…
Data sits inside its container and will disappear when (not “if”!) the container is replaced/removed (e.g. when you eventually update it). This is very not useful for a database, so we need to “persist” the data.
The -v
flag mounts a directory from the host (i.e. Linux) as a specific directory inside the container so any data that is written to said directory will exist outside the container as well. When the container is replaced/removed, the external directory will still exist, together with the data in it.
Note that I said: “specific” directory. Docker containers have specific “volumes” for mounting, detailed in their documentation. I mounted random paths out of curiosity and curious things ensued…
The syntax for the -v
flag is:
-v directory-on-host:directory-in-container:[OPTIONS]
So, in this tutorial, I want to persist the data into /mnt/data/mysql
of the Linux host. Looking up the MySQL Docker Hub, the directory inside the container with the data is /var/lib/mysql
(you won’t find this in /var/lib of the host!) so the command becomes:
-v /mnt/data/mysql:/var/lib/mysql
1.2 — …by setting the right permissions
I think this is fixed now, but I’ll keep the section just for awareness.
Having said all that in 1.1 above, you still will not see any data in /mnt/data/mysql
though if you ran the script as is with root privileges, but without the chown
line. This is because, if you access the MySQL container via shell with
docker exec -it mysql-server /bin/bash
and check the ownership of /var/lib/mysql
, you will find that it was created by mysql:mysql
. This is compared to /mnt/data/mysql
which will belong to root:root
(if you ran the script as it with root privileges). The user “mysql” cannot write to /mnt/data/mysql
!
There are any number of ways to deal with this — I just decided to deal with it in one line within the script by setting the ownership of /mnt/data/mysql
to 999:999
. I got this UID:GID by checking /etc/passwd
and /etc/group
inside the container (which, again, will be different to the host’s!). This way, the mysql user will be able to write to /mnt/data/mysql
.
I can think of “better” ways to deal with this, but for the purpose, it works. Feel free to offer suggestions though!
2.0 — Container #2: Zabbix server
I’ll only explain lines that haven’t already been covered in 1.0.
LINE 2 references the MySQL container that was created first.
LINE 8 exposes port 10051 of the host to port 10051 of the container, which is the default port that Zabbix agents use, should you choose to use them (I prefer SNMP).
Containers are isolated, so container ports need to be explicitly mapped to ports on the host. The syntax for the -p
flag is:
-p host-port:container-port
3.0 — Container #3: Zabbix web interface
I’ll only explain lines that haven’t already been covered in 1.0 or 2.0.
LINE 10 sets the time-zone. This is not mandatory, but makes sense.
LINE 12 exposes port 443 of the host to port 8443 of the container for HTTPS.
LINE 1 & 13 creates a directory on the host and mounts it for the container to receive ssl.key
& ssl.crt
to enable HTTPS. The directory is mounted read-only as the container is not expected to write to it.
3.1 — Enable/disable HTTPS
The script exposes the web interface container to only port 443. You will also need to place your SSL/TLS key and certificate as ssl.key
& ssl.crt
in /etc/ssl/apache2
of the host. Once that is done, restart all containers with docker restart $(docker ps -aq)
.
Of course, you could skip all that and replace -p 443:8443
with -p 80:8080
if you really wanted to…
TL;DR
- Start a Ubuntu server.
git clone https://github.com/scottooi/zabbix-docker-scripts.git
sudo sh zabbix-docker-scripts/install_docker_ubuntu.sh
sudo sh zabbix-docker-scripts/docker_zabbix_mysql_apache.sh
- Place
ssl.key
&ssl.crt
in/etc/ssl/apache2
of the Ubuntu host. - Restart all containers with
docker restart $(docker ps -aq)
. - Navigate to your server IP in your web browser.
- Login using Username: “Admin” & Password: “zabbix” (and change it!).
Containerised Zabbix is up and running! The second part is configuring SNMP so you actually get data into it.