Container Manager is a modular, production-ready C++ 17 service for unified container management across Docker, Podman, and more (planned). It supports REST, MQTT, POSIX Message Queue, D-Bus, gRPC (planned), Docker/Podman CLI, HTTP-API with incoming JSON/ Protobuf data with optional decryption of secure data.
Features include extensible architecture, pluggable database backend (embedded by default, Redis optional), robust logging, thread pool for all protocols, a dedicated heartbeat server for health/liveness checks, and enterprise-grade security with AES-256-GCM or ChaCha20-Poly1305 encryption.
It is designed for developers and system integrators who need a flexible, secure, and modular foundation for building container orchestration for automotive usecase.
This is a reference architecture and template project designed to demonstrate production-grade C++ patterns for container management systems. Clone, modify, and extend as needed for your specific requirements.
Example
- Need D-Bus + Podman REST API + Protobuf + AES encryption? ✅ Clone and configure.
- Want MQTT + Docker CLI + JSON + Redis database + No encryption? ✅ Clone and configure.
- Building a container orchestrator with custom runtime? ✅ Extend the runtime layer.
-
Unified Container Management:
Manage Docker and Podman containers through a single interface. -
Extensible Command Pattern:
Easily add support for new runtimes or operations. -
Multi-Protocol Support:
REST (HTTP/JSON or Protobuf), MQTT, POSIX Message Queue, D-Bus (session bus), and gRPC (planned). -
Dedicated Heartbeat Server:
Lightweight HTTP server always available on a configurable port (default: 8090) for/ping(liveness) and/health(detailed status) endpoints.
Enables health checks, monitoring, and UI integration independent of main protocol servers. -
Flexible Data Formats:
JSON or Protocol Buffers (protobuf) for high-performance or strongly-typed APIs. -
Thread Pool:
Efficient request handling using a configurable thread pool. -
Pluggable Database Backend:
Embedded database by default; Redis optional via CMake flag. -
Robust Logging:
Integrated with Google glog. -
Configurable Security:
AES-256-GCM and ChaCha20-Poly1305 encryption for all protocols. -
Python UI:
Cross-platform GUI for sending requests to the backend (see below).
App/
├── api/ # Protocol handlers (REST, MQTT, MQ, D-Bus, Heartbeat, and future protocols)
├── core/ # Business logic (service layer)
├── database/ # Database interface, embedded and Redis implementations (pluggable)
├── executor/ # Request executors (JSON, Protobuf, handle decryption)
├── runtime/ # Command pattern implementations for Docker CLI, Podman CLI, Docker API, Podman API, Podman YAML etc.
├── utils/ # Common utilities (thread pool, logging, etc.)
├── security/ # Security providers (AES-GCM, ChaCha20, Null)
├── main.cpp # Application entry point
└── third_party/ # External dependencies (nlohmann_json, httplib)
cmake .. -DENABLE_REST=ON -DENABLE_MQTT=ON -DENABLE_MSGQUEUE=ON -DENABLE_DBUS=ON -DENABLE_PROTOBUF=ON -DENABLE_ENCRYPTION=ON -DSECURITY_ALGORITHM=CHACHA20
make- See CMake flags in the next section for more options.
./CMThe server will start and listen on the enabled protocols and data formats as per your build configuration.
The heartbeat server will always be available on the configured port (default: 8090).
A dedicated lightweight HTTP server is always running for health and liveness checks, independent of the main REST or other protocol servers.
-
Liveness endpoint:
GET /ping— Returns a minimal JSON indicating the service is alive. -
Health endpoint:
GET /health— Returns a detailed JSON with service status, version, uptime, enabled features, and more.
Example:
curl http://localhost:8090/ping
# {"status": "alive", "service": "container_manager", "version": "0.7.3", "timestamp": 1751738206}
curl http://localhost:8090/health
# {
# "status": "healthy",
# "service": "container_manager",
# "version": "0.7.3",
# "timestamp": 1751738206,
# "uptime_seconds": 71,
# "heartbeat_port": 8090,
# "features": {
# "rest_enabled": true,
# "mqtt_enabled": true,
# "msgqueue_enabled": true,
# "dbus_enabled": true,
# "encryption_enabled": true
# }
# }This enables easy integration with monitoring tools, load balancers, and UI dashboards.
In this video, we explain why Container Manager was created, the problems it solves, and the advantages it brings to container orchestration and automation.
This video demonstrates how to build the project, use the Python UI, and deploy containers using different protocols and runtimes.
You can enable or disable each protocol, data format, and security feature using CMake flags:
ENABLE_REST(REST/HTTP server)ENABLE_MQTT(MQTT subscriber)ENABLE_MSGQUEUE(POSIX Message Queue)ENABLE_DBUS(D-Bus consumer)ENABLE_GRPC(gRPC, planned)ENABLE_PROTOBUF(Protobuf support; if OFF, only JSON is used)ENABLE_REDIS(Redis database backend; if OFF, embedded database is used)ENABLE_ENCRYPTION(Enable encryption for all protocols)SECURITY_ALGORITHM(Select encryption algorithm:AES_GCMorCHACHA20)
Note:
Encryption key files must be present instorage/security/as described in the architecture documentation.
The selected algorithm must match between the backend and any client sending encrypted payloads.
The following table summarizes which C++ libraries/packages are required for each protocol, data format, and feature.
Install only what you need based on your chosen CMake flags.
| Protocol / Data Format | CMake Flag | Required Packages |
|---|---|---|
| REST (HTTP/JSON) | ENABLE_REST=ON | nlohmann_json, glog, httplib |
| MQTT | ENABLE_MQTT=ON | mosquitto, nlohmann_json, glog |
| Message Queue | ENABLE_MSGQUEUE=ON | nlohmann_json, glog |
| D-Bus | ENABLE_DBUS=ON | sdbus-c++, nlohmann_json, glog |
| gRPC (planned) | ENABLE_GRPC=ON | grpc++, protobuf, nlohmann_json, glog |
| Protobuf | ENABLE_PROTOBUF=ON | protobuf |
| Redis DB | ENABLE_REDIS=ON | cpp_redis, redis-server |
| Embedded DB (default) | (default) | (no extra dependencies) |
| Encryption | ENABLE_ENCRYPTION=ON | libssl-dev (OpenSSL) |
| Heartbeat Server | (always enabled) | nlohmann_json, httplib, glog |
Notes:
- JSON is always available (unless you only enable Protobuf).
- Protobuf is optional and only needed if you want binary serialization.
- Embedded database is used unless you explicitly enable Redis.
- Encryption is ON by default and recommended for production.
- Heartbeat server is always enabled and requires no extra configuration.
Container Manager exposes a unified API for container operations over multiple protocols and data formats:
- REST:
POST /execute— Accepts JSON or Protobuf payloads.
- MQTT:
- Topic:
container/execute— Publish JSON, Protobuf, or encrypted (Base64) payloads.
- Topic:
- POSIX Message Queue:
- Queue Name:
/container_manager_queue— Send JSON, Protobuf, or encrypted (Base64) payloads.
- Queue Name:
- D-Bus:
- Bus Name:
org.container.manager - Object Path:
/org/container/manager - Interface:
org.container.manager - Method:
Execute— Accepts Base64-encoded JSON/Protobuf which can be plain/encrypted payload.
- Bus Name:
- Heartbeat:
GET /pingandGET /healthon the heartbeat server port (default: 8090).
See Usage Examples below for request formats and protocol-specific details.
{
"runtime": "docker-api",
"operation": "create",
"parameters": [
{
"container_name": "my_nginx",
"cpus": "0.5",
"memory": "128",
"pids": "10",
"restart_policy": "unless-stopped",
"image_name": "nginx:latest"
}
]
}- Use
"runtime": "docker","podman"or"podman-yaml"for CLI-based management. - Use
"runtime": "docker-api"or"podman-api"for REST API-based management.
- See
executor/proto/container_manager.protofor the schema. - Use the generated Python or C++ classes to serialize/deserialize requests.
- Example Python code to send a Protobuf request via Message Queue:
import posix_ipc
import container_manager_pb2 # Generated by protoc
req = container_manager_pb2.ContainerRequest()
req.runtime = "docker-api"
req.operation = "create"
param = req.parameters.add()
param.container_name = "my_nginx"
param.cpus = "0.5"
param.memory = "128"
param.pids = "10"
param.restart_policy = "unless-stopped"
param.image_name = "nginx:latest"
payload = req.SerializeToString()
mq = posix_ipc.MessageQueue('/container_manager_queue', posix_ipc.O_CREAT)
mq.send(payload)- POST
/execute- Send a JSON or Protobuf request as shown above to perform container operations.
- For Protobuf, set the header:
Content-Type: application/octet-stream - For encrypted payloads, set the header:
Content-Type: application/octet-streamand send the encrypted bytes.
- Topic:
container/execute - Publish Example (JSON):
mosquitto_pub -h localhost -p 1883 -t container/execute -m '{ "runtime":"docker-api", "operation":"create", "parameters":[{"container_name":"my_nginx", "cpus":"0.5", "memory":"128", "pids":"10", "restart_policy":"unless-stopped", "image_name":"nginx:latest"}]}' - Publish Example (Protobuf or Encrypted):
Use the generated Protobuf class to serialize and send the message as binary.
If encryption is enabled, Base64-encode the encrypted payload before publishing.
- Queue Name:
/container_manager_queue - Send Example (Python, JSON):
import posix_ipc mq = posix_ipc.MessageQueue('/container_manager_queue', posix_ipc.O_CREAT) mq.send('{"runtime": "podman", "operation": "create", "parameters": [{"container_name": "my_nginx", "cpus": "0.5", "memory": "64", "pids": "10", "restart_policy": "unless-stopped", "image_name":"nginx:latest"}]}')
- Send Example (Python, Protobuf or Encrypted): See the Protobuf and encryption examples above.
- Bus Name:
org.container.manager - Object Path:
/org/container/manager - Interface:
org.container.manager - Method:
Execute(accepts a JSON string or Protobuf bytes as the first argument)
Python Example (JSON):
import dbus
bus = dbus.SessionBus()
proxy = bus.get_object('org.container.manager', '/org/container/manager')
iface = dbus.Interface(proxy, dbus_interface='org.container.manager')
iface.Execute('{"runtime": "docker-api", "operation": "create", "parameters": [{"container_name": "my_nginx", "cpus": "0.5", "memory": "128", "pids": "10", "restart_policy": "unless-stopped", "image_name": "nginx:latest"}]}')Python Example (Protobuf or Encrypted):
import base64
encrypted_payload = ... # bytes from AES-GCM encryption
iface.Execute(base64.b64encode(encrypted_payload).decode())- Liveness:
curl http://localhost:8090/ping
- Health:
curl http://localhost:8090/health
Container Manager supports generating Kubernetes-style YAML files for Podman using a master template. These YAML files can be used to create and manage pods via Podman CLI commands.
-
Generate YAML File
Use the backend or UI withruntime: podman-yamlto generate a YAML file (e.g.,storage/podman_yaml/my_nginx_pod.yaml).
The YAML is based on a master template (storage/podman_yaml/master.yaml):apiVersion: v1 kind: Pod metadata: name: { { POD_NAME } } spec: containers: - name: { { CONTAINER_NAME } } image: { { IMAGE_NAME } } resources: limits: cpu: "{{CPU_LIMIT}}" memory: "{{MEMORY_LIMIT}}Mi" securityContext: pidsLimit: { { PIDS_LIMIT } } restartPolicy: "{{RESTART_POLICY}}" ports: - containerPort: 80 hostPort: 8080
Placeholders are replaced with your container parameters.
-
Run Pod via Podman CLI
podman play kube storage/podman_yaml/my_nginx_pod.yaml podman pod ps
-
Delete Pod via Podman CLI
podman play kube --down storage/podman_yaml/my_nginx_pod.yaml
Note:
Podman API support for YAML file operations (play kube) is only available in Podman v4.2.0 and above. reference link Since the current Podman version is v3.4.2, YAML via API is not implemented in this project.
All YAML-based pod operations are performed via the Podman CLI.
A cross-platform Python GUI tool is provided for easily sending container management requests to the backend.
The UI also uses the heartbeat server to show live backend status.
- Select protocol: REST (HTTP), MQTT, POSIX Message Queue, or D-Bus (session bus)
- Select data format: JSON or Protobuf
- Select runtime: Docker, Podman, Docker API, Podman API or Podman YAML.
- Select operation: create, start, stop, restart, remove, available, etc.
- Fill in container parameters (runtime, operation, resources, image, etc.)
- Enable/disable AES-GCM or ChaCha20 encryption
- Send requests directly to the backend via REST, MQTT, Message Queue, or D-Bus
- Live heartbeat indicator:
The UI pings the/pingendpoint every second and shows a green/red indicator for backend liveness. - Health details:
Click the "Health" button to view all backend health parameters, configuaration parameters in the UI.
- Select the protocol (REST, MQTT, MessageQueue, or DBus) from the dropdown.
- Select the data format (JSON or Proto).
- Select the runtime (docker, podman, docker-api, podman-api, podman-yaml) and operation (create, start, stop, restart, remove, available, etc.).
- Fill in the container parameters (CPUs, memory, image, etc.).
- Choose the encryption algorithm (None, AES-256-GCM, or ChaCha20-Poly1305).
- Click "Send Request" to send the request to the backend.
- The UI will show a confirmation or error message after sending the request.
- Monitor backend health:
The UI's heartbeat indicator and Health button use the always-on heartbeat server.
The UI automatically handles serialization, encryption, and protocol-specific details (such as Base64 encoding for D-Bus and MQTT).
- Python 3.7+
- requests
- paho-mqtt
- posix_ipc
- dbus-python
- protobuf
- pycryptodome
- Tkinter (usually included with Python)
Install dependencies:
pip install requests paho-mqtt posix_ipc dbus-python protobuf pycryptodomecd ui
python container_creator_app.py-
Add a new runtime:
Implement new command classes inApp/runtime/and register them inCommandFactory. -
Add a new operation:
Extend the command pattern and update the service layer. -
Add a new protocol:
Implement a new API handler inApp/api/(e.g., for Message Queue, D-Bus, gRPC, MQTT) and register it in the main application. -
Add a new data format:
Implement a newRequestExecutor(e.g., for Protobuf) inApp/executor/and update the API handler to use it. -
Change database backend:
Implement theIDatabaseHandlerinterface for your preferred database (SQL, NoSQL, etc.) and update the service to use it. -
Add a new security algorithm:
Implement a new security provider inApp/security/by extending theISecurityProviderinterface, and update the CMake configuration and executor logic to support it.
- For a comprehensive overview of the system design, security, and extensibility, see Architecture Documentation.
- Doxygen HTML docs: After building, open
docs/doxygen/html/index.htmlin your browser.
Contributions are welcome! Please open issues or pull requests for bug fixes, new features, or documentation improvements.
This project is licensed under the MIT License.
