A lightweight process orchestration tool written in C, inspired by basic Docker concepts.
Dockerman is intentionally small and focuses on understanding the operating-system primitives behind a container-like CLI rather than trying to implement Docker itself.
- Start multiple configured services with one command
- Create service processes using
fork() - Execute service commands using
/bin/sh -candexec-style process replacement - Track service PIDs using PID files
- Check whether a service is running
- Stop services using
SIGTERM - Display service status with PID information
- Capture service stdout/stderr into per-service log files
- Keep configuration, process management, monitoring, logging, and CLI handling in separate C modules
dockerman/
├── main.c # CLI entry point and command handling
├── config.c # Service definitions
├── config.h
├── process.c # fork, PID tracking, signals and process lifecycle
├── process.h
├── monitor.c # Service status display
├── monitor.h
├── logger.c # Timestamped service lifecycle logs
├── logger.h
├── utils.c # CLI usage/help
├── utils.h
├── Makefile
├── logs/ # Service output and lifecycle logs
└── run/ # Runtime PID files
Services are defined in config.c.
The current demo contains two services:
workerweb
Each service has a name and a shell command that continuously produces output.
Running:
./dockman upcauses Dockerman to:
- Read the configured services.
- Call
fork()for each service. - In the child process, redirect stdout/stderr to the service log file.
- Execute the configured shell command.
- In the parent process, store the child PID in
run/<service>.pid.
Example:
./dockman up
|
+-- worker -> fork() -> service process
|
+-- web -> fork() -> service process
Dockerman stores each service PID in a small PID file:
run/worker.pid
run/web.pid
For ps, the program reads the PID and uses kill(pid, 0) to check whether the process is still alive.
Running:
./dockman stopreads the stored PIDs and sends:
SIGTERM
to the corresponding service processes.
The PID files are then removed.
Each service has its own log file:
logs/worker.log
logs/web.log
The child process redirects:
stdout -> service log
stderr -> service log
This allows the service's output to be inspected later.
You need a Linux environment with GCC and Make.
Check that they are installed:
gcc --version
make --versionBuild the project:
makeTo rebuild from scratch:
make clean
make./dockman upExample:
Started worker (pid 1234)
Started web (pid 1235)
./dockman psExample:
SERVICE STATUS PID
--------------------------------
worker running 1234
web running 1235
./dockman logs worker./dockman logs web./dockman stopA quick demonstration can be run with:
make clean
make
./dockman up
./dockman ps
./dockman logs worker
./dockman logs web
./dockman stop
./dockman psDockerman is not a Docker replacement and does not provide full container isolation.
It does not currently implement:
- Linux namespaces
- cgroups
- filesystem/container root isolation
- virtual networking
- container images
- layered filesystems
- resource limits
- container registries
The goal of this project is to demonstrate the basic process-management layer that can be used as a foundation for a more complete container runtime.
Possible next steps would be:
- Add Linux namespaces for process, network, mount, and hostname isolation.
- Add cgroups for CPU and memory limits.
- Add filesystem isolation using a dedicated root filesystem.
- Add a configuration file instead of hard-coded services.
- Add service restart policies.
- Add basic networking between services.
- C
- Linux/POSIX system calls
fork()exec//bin/sh -ckill()and Unix signals- PID files
- GCC
- GNU Make
This project was built as a small systems-programming project to explore how process creation, execution, signals, PID management, and logging can be combined to build a simple service orchestration tool.