Lifebox M&E System - Docker Architecture

Introduction

This documentation provides a comprehensive overview of the Docker-based architecture for the Lifebox Monitoring & Evaluation (M&E) System. The system is containerized using Docker and orchestrated with Docker Compose, making it portable and scalable across different environments.

Key Features

  • Containerized Architecture: All components run in isolated Docker containers
  • Microservices Design: Independent services for database, analytics, documentation, and tracking
  • CI/CD Pipeline: Automated build and deployment with GitLab CI
  • Scalability: Easily scale individual services as needed
  • Environment Consistency: Consistent environments from development to production
  • Infrastructure as Code: All infrastructure defined in Docker Compose files

System Overview

32
Component Description
PostgreSQL Database Primary analytics database for M&E data (lifebox_mesystem)
MariaDB Database Application database for Matomo analytics and forms (lifeboxme_matomo, lifeboxme_forms)
Metabase Business intelligence and reporting dashboard
Matomo Web analytics and tracking platform
pgAdmin PostgreSQL administration tool
phpMyAdmin MariaDB administration tool
MkDocs Documentation site for the Lifebox M&E System

Getting Started

Prerequisites

Before you begin, ensure you have the following installed:

  • Docker (minimum version 20.10.x)
  • Docker Compose (minimum version 1.29.x)
  • Git (for cloning the repository)

Installation Steps

1 Clone the Repository

Terminal Command
git clone https://your-repository-url/lifeboxme.git cd lifeboxme

2 Configure Environment

Copy .env.dev to .env
cp .env.dev .env # Edit .env with your specific configuration if needed

3 Start the System

Start Command
docker-compose -p lifeboxme up -d

4 Access Services

Service URL Credentials
Metabase Analytics http://localhost:4000 lifebox@cloud.merqconsultancy.org / lifeboxme0
pgAdmin (PostgreSQL Admin) http://localhost:5445 dev@merqconsultancy.org / lifeboxme@sys
phpMyAdmin (MariaDB Admin) http://localhost:3309 lifeboxme_system / lifeboxme_system
Matomo Analytics http://localhost:8088 Configure during first setup
MkDocs Documentation http://localhost:8558 Public access

System Architecture

The Lifebox M&E system follows a containerized microservices architecture. Each component runs in its own Docker container, communicating through a dedicated network.

Data Flow

The system follows this data flow pattern:

  1. User requests are handled by Metabase or Matomo web interfaces
  2. Metabase queries PostgreSQL (lifebox_mesystem) for M&E analytics
  3. Matomo tracks web analytics and stores data in MariaDB (lifeboxme_matomo)
  4. Lifebox Forms data is stored in MariaDB (lifeboxme_forms)
  5. pgAdmin and phpMyAdmin provide database management interfaces
  6. MkDocs serves documentation for the system

Network Architecture

The system uses a custom bridge network (lifeboxnet) with a configurable subnet (default: 192.168.47.0/24). Each service has a static IP address within this subnet:

Service IP Address Port (Host) Description
lifeboxme_db (PostgreSQL) 192.168.47.2 5432 Primary analytics database
lifeboxme_pgadmin 192.168.47.3 5445 PostgreSQL administration
lifeboxme_metabase 192.168.47.4 4000 Analytics dashboard
lifeboxme_mariadb 192.168.47.5 3306 (internal) Application database
lifeboxme_phpmyadmin 192.168.47.6 3309 MariaDB administration
lifeboxme_matomo 192.168.47.7 8088 Web analytics platform
mkdocs 192.168.47.8 8558 Documentation site

Docker Services

The Docker Compose file defines the following services that make up the Lifebox M&E system:

lifeboxme_db (PostgreSQL)

Primary analytics database for the Lifebox M&E system.

  • Image: postgres:17-alpine
  • Database: lifebox_mesystem
  • User: postgres
  • Network IP: 192.168.47.2
  • Port: 5432 (mapped to host)
PostgreSQL 17 Analytics

lifeboxme_mariadb

Application database for Matomo analytics and Lifebox Forms.

  • Image: mariadb:11.2.4
  • Databases: lifeboxme_matomo, lifeboxme_forms
  • User: lifeboxme_system
  • Network IP: 192.168.47.5
MariaDB 11.2 Application DB

lifeboxme_metabase

Business intelligence and analytics dashboard.

  • Image: metabase/metabase:latest
  • Port: 4000:3000
  • Database: PostgreSQL (lifebox_mesystem)
  • Network IP: 192.168.47.4
Port 4000 Analytics

lifeboxme_matomo

Web analytics platform for tracking and reporting.

  • Image: matomo:latest
  • Port: 8088:80
  • Database: MariaDB (lifeboxme_matomo)
  • Network IP: 192.168.47.7
Port 8088 Analytics

lifeboxme_pgadmin

PostgreSQL administration tool.

  • Image: dpage/pgadmin4:latest
  • Port: 5445:80
  • Email: dev@merqconsultancy.org
  • Network IP: 192.168.47.3
Port 5445 Management

lifeboxme_phpmyadmin

MariaDB administration tool.

  • Image: phpmyadmin:5.2.1
  • Port: 3309:80
  • Network IP: 192.168.47.6
Port 3309 Management

mkdocs

Documentation site for the Lifebox M&E System.

  • Build: Custom Dockerfile (mkdocs_app target)
  • Port: 8558:8558
  • Network IP: 192.168.47.8
Port 8558 Documentation

Build Process

The system uses Docker Compose for building and managing services. Most services use official images, while the MkDocs service uses a custom Dockerfile.

Dockerfile Structure

The Dockerfile defines multiple build targets:

  1. mkdocs_app: Python-based MkDocs documentation server
  2. Additional targets can be added as needed for custom PHP applications

Building the System

To build the entire system:

Build Command
docker-compose -p lifebox build --no-cache

Building Individual Components

To build specific services:

Build MkDocs Service
docker-compose -p lifebox build mkdocs

Deployment

The system can be deployed to different environments using Docker Compose.

Starting the System

To start all services in detached mode:

Start Command
docker-compose -p lifeboxme up -d

Stopping the System

To stop all services while preserving data volumes:

Stop Command
docker-compose -p lifebox down

Full Cleanup

To stop all services and remove all resources:

Cleanup Command
docker-compose -p lifebox down --volumes --rmi all

View Logs

Follow Logs
docker-compose -p lifebox logs -f

Configuration

The system is configured through environment variables in the .env file.

Key Configuration Files

  • docker-compose.yml: Main service definitions and configurations
  • .env.dev / .env.prod: Environment variables for development/production
  • Dockerfile: Build instructions for custom images
  • pgadmin-servers.json: Pre-configured pgAdmin servers

Environment Variables

Variable Service Description Default Value
POSTGRES_DB PostgreSQL Primary database name lifebox_mesystem
POSTGRES_USER PostgreSQL Database username postgres
POSTGRES_PASSWORD PostgreSQL Database password mikeintosh
MARIADB_DATABASE MariaDB Matomo database name lifeboxme_matomo
MARIADB_USER MariaDB Database username lifeboxme_system
MARIADB_PASSWORD MariaDB Database password lifeboxme_system
MB_ADMIN_EMAIL Metabase Metabase admin email lifebox@cloud.merqconsultancy.org
MB_ADMIN_PASSWORD Metabase Metabase admin password lifeboxme0
PGADMIN_DEFAULT_EMAIL pgAdmin pgAdmin admin email dev@merqconsultancy.org
PGADMIN_DEFAULT_PASSWORD pgAdmin pgAdmin admin password lifeboxme@sys
NETWORK_SUBNET All Services Docker network subnet 192.168.47.0/24

CI/CD Pipeline

The system uses GitLab CI for automated build and deployment.

Pipeline Stages

  1. Build: Build custom Docker images (MkDocs, etc.)
  2. Deploy: Deploy to production environment

Build Stage

Builds custom images and pushes to container registry:

.gitlab-ci.yml (Build)
build-mkdocs: stage: build image: docker:24.0.7 services: - docker:24.0.7-dind script: - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin - docker build --target mkdocs_app -t $DOCKER_REGISTRY/lifebox-mkdocs:latest . - docker push $DOCKER_REGISTRY/lifebox-mkdocs:latest only: - main

Deploy Stage

Deploys the application to production environment:

.gitlab-ci.yml (Deploy)
deploy-production: stage: deploy image: docker:24.0.7 services: - docker:24.0.7-dind tags: - lifebox-production script: - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin - docker-compose -p lifebox down - docker-compose -p lifebox pull - docker-compose -p lifeboxme up -d --build - docker image prune -f only: - main

API Documentation

The Lifebox M&E system provides RESTful APIs for accessing M&E data. All endpoints are available through the PHPRunner REST API implementation.

Base URL: https://mne.lifebox.org/app/api/v1.php

Authentication

All API endpoints require authentication. Two authentication methods are supported:

Method 1: API Key (Recommended)

Include the API key as a parameter in the request:

API Key Example
https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=list&apikey=$2y$10$CPrlfPZs4wI0QHECfzUUq.0eyCgbkRwOpNOpSpnyVDnmOVOav2qTm

Method 2: HTTP Basic Authentication

Basic Auth Example
curl --user username:password "https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=list"

Available API Tables

Table Name Description Key Fields
lbpmi_data_values M&E data values for indicators and data elements data_value_id, data_element_id, period_year, region_id, value
lbpmi_indicator_actuals Indicator actual values for M&E reporting actual_id, indicator_id, period_year, region_id, actual_value

Data Values API (lbpmi_data_values)

GET List Data Values ?table=lbpmi_data_values&action=list

Parameters

Parameter Description Example
records Number of records to return records=5
skip Records to skip (pagination) skip=10
q Advanced search filter q=(region_id~equals~8)
qs Full-text search qs=Abush

Example Request

List Data Values (5 records)
https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=list&records=5&skip=0&apikey=YOUR_API_KEY

Sample Response

Response JSON
{ "data": [ { "data_value_id": "2", "data_element_id": "5", "period_type": "Quarterly", "period_year": "2026", "period_quarter": "1", "period_month": "3", "period_week": null, "period_day": "2026-03-20", "region_id": "8", "country_id": null, "facility_id": null, "value": "300", "stored_by": "Mr. Abush (Data Manager)", "created": "2026-03-20 02:53:50", "last_updated": "2026-03-20 02:55:54", "deleted": "f", "data_source": "", "source_detail": "", "value_type": "Loading..." } ], "success": true }
GET View Single Data Value ?table=lbpmi_data_values&action=view&editid1={id}
View Data Value by ID
https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=view&editid1=2&apikey=YOUR_API_KEY
POST Insert Data Value ?table=lbpmi_data_values&action=insert
Insert New Data Value
curl -X POST "https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=insert&apikey=YOUR_API_KEY" \ -d "data_element_id=10&period_year=2026®ion_id=8&value=500"
POST Update Data Value ?table=lbpmi_data_values&action=update
Update Existing Data Value
curl -X POST "https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=update&apikey=YOUR_API_KEY" \ -d "editid1=2&value=350&stored_by=System User"
POST Delete Data Value ?table=lbpmi_data_values&action=delete&editid1={id}

Indicator Actuals API (lbpmi_indicator_actuals)

GET List Indicator Actuals ?table=lbpmi_indicator_actuals&action=list

Example Request

List Indicator Actuals (5 records)
https://mne.lifebox.org/app/api/v1.php?table=lbpmi_indicator_actuals&action=list&records=5&skip=0&apikey=YOUR_API_KEY

Sample Response

Response JSON
{ "data": [ { "actual_id": "2", "indicator_id": "28", "period_type": "Quarterly", "period_year": "2026", "period_quarter": "1", "period_month": "3", "region_id": "8", "country_id": null, "facility_id": null, "actual_value": "5", "is_calculated": "f", "calculation_timestamp": "2026-03-19 03:20:17", "created_at": "2026-03-19 03:20:17", "updated_at": null } ], "success": true }
GET View Single Indicator Actual ?table=lbpmi_indicator_actuals&action=view&editid1={id}
View Indicator Actual by ID
https://mne.lifebox.org/app/api/v1.php?table=lbpmi_indicator_actuals&action=view&editid1=2&apikey=YOUR_API_KEY

Advanced Filtering

Filter by Region

Filter: region_id = 8
https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=list&q=(region_id~equals~8)&apikey=YOUR_API_KEY

Filter by Year and Quarter

Filter: period_year = 2026 AND period_quarter = 1
https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=list&q=(period_year~equals~2026)AND(period_quarter~equals~1)&apikey=YOUR_API_KEY

Filter by Data Element ID

Filter: data_element_id = 42
https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=list&q=(data_element_id~equals~42)&apikey=YOUR_API_KEY

API Troubleshooting

Issue Solution
Authentication failures Verify API key is valid. Check that the API key parameter is correctly formatted as &apikey=...
Empty data response Check if the table name is correct. Verify that the user has permissions to access the data.
Filter not working Verify filter syntax. Use the format: q=(field~operator~value) with operators like equals, contains, gt, lt, etc.
Debugging API calls Use verbose mode: curl -v "https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=list"
Debugging Example
curl -v "https://mne.lifebox.org/app/api/v1.php?table=lbpmi_data_values&action=list&apikey=YOUR_API_KEY"

Database Documentation

The system uses two primary databases for different services.

Database Type Username Host Port Purpose
lifebox_mesystem PostgreSQL postgres lifeboxme_db 5432 Primary M&E analytics database
lifeboxme_matomo MariaDB lifeboxme_system lifeboxme_mariadb 3306 Matomo web analytics database
lifeboxme_forms MariaDB lifeboxme_system lifeboxme_mariadb 3306 Lifebox Forms application database

Database Access Commands

Access PostgreSQL
docker exec -it lifeboxme_db psql -U postgres -d lifebox_mesystem
Access MariaDB
docker exec -it lifeboxme_mariadb mariadb -u lifeboxme_system -plifeboxme_system lifeboxme_matomo

Key Tables

  • lbpmi_data_values: Stores M&E data values with periods, regions, and values
  • lbpmi_indicator_actuals: Stores indicator actual values for reporting
  • matomo_* tables: Matomo analytics data tables

Virtualmin Hosting

Production deployment on Virtualmin requires specific configuration for Docker services.

Virtualmin Server Requirements

  • Ubuntu 22.04 LTS
  • 4 vCPU cores
  • 8GB RAM minimum
  • 50GB storage
  • Docker and Docker Compose installed

Configuration Steps

1 Create Virtual Server

Virtualmin Command
sudo virtualmin create-domain --domain mne.lifebox.org --pass 'securepassword' --desc "Lifebox M&E System"

2 Configure Proxy for Metabase

Virtualmin Command
sudo virtualmin create-proxy --domain mne.lifebox.org/metabase/ \ --path / --url http://127.0.0.1:4000/

3 SSL Configuration

Virtualmin Command
sudo virtualmin install-cert --domain mne.lifebox.org --letsencrypt

Deployment to Production

Transfer Docker Setup
scp -r lifeboxme/ user@mne.lifebox.org:/opt/lifeboxme
Start Production System
cd /opt/lifeboxme cp .env.prod .env docker-compose -p lifeboxme up -d

Troubleshooting

Common issues and solutions for the Docker-based Lifebox M&E system.

Common Problems

Issue Possible Cause Solution
Containers not starting Port conflicts Check for other services using ports 4000, 5445, 3309, 8088, 8558. Change ports in .env if needed.
Database connection errors Incorrect credentials in .env Verify environment variables in .env file match your configuration
Permission issues with volumes Volume ownership/permissions Ensure data directories have correct permissions: sudo chown -R 999:999 ./data/postgres-data (PostgreSQL uses UID 999)
Metabase not loading PostgreSQL connection issue Check PostgreSQL logs: docker logs lifeboxme_db. Verify MB_DB_HOST is set correctly.
Matomo database connection error MariaDB not ready Wait for MariaDB health check to pass, then restart Matomo: docker restart lifeboxme_matomo
pgAdmin cannot connect to PostgreSQL Server configuration missing Use the pre-configured servers.json file or manually add server: host=lifeboxme_db, port=5432

Useful Commands

View All Container Logs
docker-compose -p lifebox logs -f
View Specific Service Logs
docker-compose -p lifebox logs -f lifeboxme_metabase
Rebuild Single Service
docker-compose -p lifeboxme up -d --build mkdocs
Check Container Health Status
docker ps --format "table {{.Names}}\t{{.Status}}"
Clean Docker System
docker system prune -a -f --volumes