Simplified Zabbix Install: Step-by-Step with Docker and Portainer

Fredrik Maxfield
9 min readDec 12, 2023

Zabbix provides robust capabilities for keeping a close eye on networks, servers, and applications. The use of containerization has simplified the deployment of Zabbix, making it an ideal choice for IT enthusiasts looking to set up monitoring in their home lab or spin up a Proof of Concept (POC).

This article is primarily for those who want to set up a Zabbix instance quickly in a isolated environment. The steps provided are streamlined to make the setup easy and fast. However, it’s important to realize that this approach might not be suitable for a real production environment.

In a production setup, deploying Zabbix is a serious task that involves careful planning, strong security measures and considerations for making it scale as your organization’s needs grow and change. Therefore, before relying on Zabbix for critical tasks, proper planning is necessary. For production deployment, always consult the official Zabbix documentation and adhere to industry best practices.

Why Zabbix in Docker?

Deploying Zabbix within Docker containers offers several advantages. It encapsulates the monitoring environment, making it portable and consistent across different platforms. It also isolates dependencies, ensuring that your monitoring system operates without conflicts. Dockerized Zabbix is easily updateable, maintainable, and scalable.

Using Portainer for Simplified Deployment

Portainer, a user-friendly management UI for Docker, simplifies the deployment process. It provides a visual interface for handling Docker environments, eliminating the need to work with complex command-line instructions.

Prerequisites

Before we proceed with the deployment process, here are the prerequisites:

  • Linux Server: You should have a Linux server up and running. I’m using Ubuntu Server 22.04.3.
  • Docker: Docker should be installed on your server.
  • Portainer: You should have Portainer installed to manage your Docker containers. If you haven’t already, you can install Portainer following the official documentation (https://docs.portainer.io/start/install-ce).

Step by Step: Deploying Zabbix with Docker and Portainer

Now that we’ve covered the prerequisites, let’s dive into the process of deploying Zabbix using Docker and Portainer.

Step 1: Set Up Environment Variables

The Zabbix deployment relies on an .env file to configure essential environment variables for setting up the PostgreSQL database and defining the Zabbix network port. Here's a breakdown of the variables found in the .env file:

  • POSTGRES_USER: Define the username for PostgreSQL.
  • POSTGRES_PASSWORD: Set a strong password for PostgreSQL.
  • POSTGRES_DB: Specify the name of the PostgreSQL database for Zabbix.
  • PHP_TZ: Determine the time zone for Zabbix PHP components.
  • ZABBIX_FRONTEND_PORT: Set the port for accessing the Zabbix web interface.

Below is the .env file used in this guide. Please replace “strongpassword” with a strong and unique password and adjust Time Zone and Port if necessary.

POSTGRES_USER=zabbix
POSTGRES_PASSWORD=strongpassword
POSTGRES_DB=zabbix
PHP_TZ=Europe/London
ZABBIX_FRONTEND_PORT=8080

Step 2: Create a Docker Compose File

The heart of our Zabbix deployment lies in the Docker Compose YAML file. This file defines the Zabbix components, their configurations, and the volumes for data persistence. Below are three versions that cover different monitoring needs.

Version 1: Basic Setup

This version deploys the Zabbix agent without granting it access to the Docker socket (/var/run/docker.sock). It's the most secure option in terms of minimizing potential attack surfaces and adheres to Docker best practices by keeping containers isolated and focused on running a single service.

version: '3.7'

services:
postgresql-server:
image: postgres:latest
container_name: postgresql-server
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgresql-data:/var/lib/postgresql/data

zabbix-server:
image: zabbix/zabbix-server-pgsql:latest
container_name: zabbix-server
restart: unless-stopped
depends_on:
- postgresql-server
environment:
DB_SERVER_HOST: postgresql-server
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "10051:10051"
volumes:
- zabbix-server-data:/var/lib/zabbix
- zabbix-snmptraps-data:/var/lib/zabbix/snmptraps
- zabbix-export-data:/var/lib/zabbix/export

zabbix-web-nginx-pgsql:
image: zabbix/zabbix-web-nginx-pgsql:latest
container_name: zabbix-web
restart: unless-stopped
depends_on:
- postgresql-server
- zabbix-server
environment:
DB_SERVER_HOST: postgresql-server
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ZBX_SERVER_HOST: zabbix-server
PHP_TZ: ${PHP_TZ}
ports:
- "${ZABBIX_FRONTEND_PORT}:8080"
volumes:
- zabbix-web-data:/usr/share/zabbix

zabbix-agent:
image: zabbix/zabbix-agent:latest
container_name: zabbix-agent
restart: unless-stopped
depends_on:
- zabbix-server
environment:
ZBX_HOSTNAME: "zabbix-server"
ZBX_SERVER_HOST: zabbix-server
ZBX_SERVER_PORT: '10051'
ZBX_SERVER_ACTIVE: zabbix-server

volumes:
postgresql-data:
zabbix-server-data:
zabbix-snmptraps-data:
zabbix-export-data:
zabbix-web-data:

Version 2: Zabbix Agent with Docker Socket Access

This version mounts the Docker socket inside the Zabbix agent container, enabling it to directly monitor the Docker daemon and containers. This setup enables monitoring of Docker performance and status but introduces security risks by giving the container elevated access to the host’s Docker engine.

version: '3.7'

services:
postgresql-server:
image: postgres:latest
container_name: postgresql-server
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgresql-data:/var/lib/postgresql/data

zabbix-server:
image: zabbix/zabbix-server-pgsql:latest
container_name: zabbix-server
restart: unless-stopped
depends_on:
- postgresql-server
environment:
DB_SERVER_HOST: postgresql-server
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "10051:10051"
volumes:
- zabbix-server-data:/var/lib/zabbix
- zabbix-snmptraps-data:/var/lib/zabbix/snmptraps
- zabbix-export-data:/var/lib/zabbix/export

zabbix-web-nginx-pgsql:
image: zabbix/zabbix-web-nginx-pgsql:latest
container_name: zabbix-web
restart: unless-stopped
depends_on:
- postgresql-server
- zabbix-server
environment:
DB_SERVER_HOST: postgresql-server
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ZBX_SERVER_HOST: zabbix-server
PHP_TZ: ${PHP_TZ}
ports:
- "${ZABBIX_FRONTEND_PORT}:8080"
volumes:
- zabbix-web-data:/usr/share/zabbix

zabbix-agent:
image: zabbix/zabbix-agent:latest
container_name: zabbix-agent
restart: unless-stopped
depends_on:
- zabbix-server
environment:
ZBX_HOSTNAME: "zabbix-server"
ZBX_SERVER_HOST: zabbix-server
ZBX_SERVER_PORT: '10051'
ZBX_SERVER_ACTIVE: zabbix-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock

volumes:
postgresql-data:
zabbix-server-data:
zabbix-snmptraps-data:
zabbix-export-data:
zabbix-web-data:

Version 3: Zabbix Agent with Host Filesystem Access

This version is designed for advanced monitoring scenarios where the Zabbix agent container requires extensive access to the host’s system and Docker environment.

By mounting the host’s entire filesystem and the /var/run directory into the Zabbix agent container, and running the container in privileged mode, this configuration enables the Zabbix agent to perform in-depth monitoring of the host system and Docker containers.

version: '3.7'

services:
postgresql-server:
image: postgres:latest
container_name: postgresql-server
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgresql-data:/var/lib/postgresql/data

zabbix-server:
image: zabbix/zabbix-server-pgsql:latest
container_name: zabbix-server
restart: unless-stopped
depends_on:
- postgresql-server
environment:
DB_SERVER_HOST: postgresql-server
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "10051:10051"
volumes:
- zabbix-server-data:/var/lib/zabbix
- zabbix-snmptraps-data:/var/lib/zabbix/snmptraps
- zabbix-export-data:/var/lib/zabbix/export

zabbix-web-nginx-pgsql:
image: zabbix/zabbix-web-nginx-pgsql:latest
container_name: zabbix-web
restart: unless-stopped
depends_on:
- postgresql-server
- zabbix-server
environment:
DB_SERVER_HOST: postgresql-server
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ZBX_SERVER_HOST: zabbix-server
PHP_TZ: ${PHP_TZ}
ports:
- "${ZABBIX_FRONTEND_PORT}:8080"
volumes:
- zabbix-web-data:/usr/share/zabbix

zabbix-agent:
image: zabbix/zabbix-agent:latest
container_name: zabbix-agent
restart: unless-stopped
depends_on:
- zabbix-server
environment:
ZBX_HOSTNAME: "zabbix-server"
ZBX_SERVER_HOST: zabbix-server
ZBX_SERVER_PORT: '10051'
ZBX_SERVER_ACTIVE: zabbix-server
volumes:
- /:/rootfs:ro
- /var/run:/var/run
privileged: true

volumes:
postgresql-data:
zabbix-server-data:
zabbix-snmptraps-data:
zabbix-export-data:
zabbix-web-data:

Understanding the Docker Compose Files

The Docker Compose files orchestrates a Zabbix monitoring system with four services:

1. PostgreSQL Server:

  • Uses the latest official PostgreSQL image.
  • Names the container postgresql-server.
  • Ensures the container restarts unless explicitly stopped.
  • Sets database user, password, and name from an .env file.
  • Persists database data in a volume called postgresql-data.

2. Zabbix Server:

  • Utilizes the latest Zabbix server image compatible with PostgreSQL.
  • Depends on the PostgreSQL container, ensuring it starts first.
  • Exposes port 10051 for Zabbix server communications.
  • Maintains Zabbix configuration and operational data across restarts using three volumes: zabbix-server-data, zabbix-snmptraps-data, and zabbix-export-data.

3. Zabbix Web Interface:

  • Runs the latest Zabbix web interface with Nginx and PostgreSQL support.
  • Depends on both PostgreSQL and Zabbix server containers to start after they’re up.
  • Binds a dynamic port specified in the .env file to port 8080 in the container for web access.
  • Uses a volume, zabbix-web-data, to store web-related files.

4. Zabbix Agent:

Version 1 (Basic Configuration)

  • Zabbix agent installed without additional privileges.
  • Limited to network-level checks and basic system metrics; cannot monitor detailed Docker metrics or other containers’ internals.
  • Offers the highest level of security due to lack of elevated access.

Version 2 (Docker Socket Access)

  • Zabbix agent within a container has access to the Docker socket.
  • Enables monitoring of Docker daemon and containers, providing detailed insights into container statuses, resource usage, and more.
  • Increased security risk due to elevated access. Needs careful security measures to mitigate potential vulnerabilities.

Version 3 (Host Filesystem and /var/run Access)

  • Zabbix agent within a container has access to the host’s entire filesystem and /var/run.
  • Allows for comprehensive monitoring of the host system and Docker environment, including detailed system and Docker metrics.
  • High security risk because of privileged access. Requires strict security control and monitoring to safeguard the system.

Volumes:

Defines persistent storage to retain data for the PostgreSQL server, Zabbix server, web interface, and Zabbix agent, ensuring data is not lost when containers are stopped or updated.

Finding the Balance

Picking the right setup is about finding a balance between what you need to monitor and keeping your Docker environment safe and easy to handle. Although the detailed monitoring from Versions 2 and 3 might be perfect for some situations, Version 1 sticks closer to Docker best practices regarding security and container isolation, making it a good starting point for most.

Step 3: Deploy the Stack with Portainer

Access Portainer and navigate to the “Stacks” section and select “Add stack”. Upload your .yml and .env file and Portainer will parse it to prepare the services for deployment. Verify everything and when ready hit “Deploy the stack”.

Portainer — Prepare Stack for deployment.

Shortly after Portainer should notify that the deployment was successful.

Portainer — Stack successfully deployed.

After deployment has completed verify that all containers are running and check the logs for any errors.

Portainer — Containers

Step 4: Access Zabbix Frontend

After successful deployment, access the Zabbix Frontend using the specified host port (http://<your-servers-ip>:8080). Here, you can begin configuring your monitoring environment.

Deployment completed — successfully accessing Zabbix Frontend

You can log in the first time using the default Admin user.
Username: Admin
Password: zabbix

It’s highly advised to change the Admin account password after deployment!

Post-Deployment Step: Associating the Zabbix Agent with the Zabbix Server Host

Once your Zabbix stack is deployed via Portainer the next step is linking the Zabbix agent to the Zabbix server host.

Zabbix Frontend — Problem “Zabbix Agent is not available”
  • Access Zabbix Frontend
  • Locate Your Zabbix Server Host: Head to “Configuration” > “Hosts” and find your Zabbix server in the host list.
  • Edit Zabbix Server Host Settings: Click on the name of your Zabbix server host to access its settings.

Configure Agent Details:

  • If an agent interface for the Zabbix server is already present, check that the IP address or DNS name correctly points to the Zabbix agent’s location (running as a Docker container).
  • If no agent interface is listed, click “Add” to create one. Choose “Agent” as the type, and input the IP address or DNS name of the Zabbix agent, ensuring the port aligns with your Zabbix agent configuration, in this case port 10050.
  • Apply Changes: Confirm the agent interface details are correct, then click “Update” to save your modifications.
  • Verify Connectivity: To confirm successful monitoring of the Zabbix server by the agent, go to “Monitoring” > “Latest data” and Filter by your Zabbix server host to see collected data, indicating the agent’s proper association and functionality. There might be a delay before all items start populating with data.
  • Additionally, you can verify the status of the Zabbix agent by navigating to “Monitoring” > “Data collection” and selecting “Hosts” from the dropdown menu. Here, look for the agent availability status next to your Zabbix server host. Initially, this might be indicated by a red icon, signifying no communication. Once the Zabbix agent is successfully connected and communicating with the Zabbix server, this icon will change to green.
Data Collection > Hosts — Zabbix Server agent availability

Following these steps ensures the Zabbix server is effectively monitored by the Zabbix agent, offering a comprehensive view of the server’s performance and health.

Conclusion and Best Practices

Installing Zabbix with Docker and Portainer in your home lab allows you to enjoy the benefits of efficient enterprise monitoring without the complexities of a production environment. Use this setup as a foundation to explore the capabilities of Zabbix and refine your monitoring skills.

For production deployments, it’s essential to carefully plan your Zabbix setup, consider high availability, security measures, and scalability. Consult the official Zabbix documentation and follow industry best practices to ensure the reliability and performance of your monitoring solution.

--

--

Fredrik Maxfield

Sysadmin interessted in Zabbix, VMware, MS365, IT security and self-hosting. In my spare time I explore homelab projects. Sharing insights, findings and tips.