Running Monit as PID 1 (init process) in a container provides several key benefits:
-
Process Reaping: In containers, the PID 1 process is responsible for "reaping" zombie processes - processes that have completed but whose exit status hasn't been collected. Without proper reaping, zombies accumulate and consume resources. Monit properly manages this critical init responsibility.
-
Signal Handling: PID 1 must handle and forward signals properly. When a container receives a shutdown signal (SIGTERM), Monit ensures all child processes shut down gracefully before the container stops, preventing data corruption.
-
Consolidated Functionality: Rather than using separate tools (like tini, dumb-init, or s6) alongside Monit, using Monit directly as PID 1 reduces complexity and container bloat.
-
Built-in Monitoring: Unlike other init replacements, Monit also provides robust service monitoring, automatic restarts, and notifications, making it a comprehensive solution for container health.
-
Ordered Startup and Dependencies: Monit can start services in a specific sequence and manage dependencies between them. This is crucial for multi-service containers where certain services must be fully operational before others start, a capability typically found only in full init systems like systemd.
-
Improved Reliability: Proper init functionality prevents common issues in containerized applications such as orphaned processes, improper shutdowns, and resource leaks.
This approach is particularly valuable for production containers where reliability, proper resource management, and clean application lifecycle handling are critical.
A guide for testing Monit's ability to function as the init process (PID 1) in a Docker container, specifically targeting the latest Monit 5.35.x version with init implementation.
You've already created the directory structure:
monit-docker-test/
├── Dockerfile
├── monitrc # Will be placed at /etc/monitrc in the container
└── scripts/
├── program.sh
├── process.sh
└── check_zombies.sh
-
program.sh: Sleeps for 10 seconds and exits
- Checks for zombie processes before running
- Logs execution to
/results/program_execution.log
-
process.sh: Writes its PID to a file, sleeps for 30 min, and exits
- Checks for zombie processes before running
- Logs execution to
/results/process_execution.log - Handles SIGTERM gracefully
-
check_zombies.sh: Utility to check for zombie processes
- Can be run manually to verify Monit is properly reaping child processes
This guide provides step-by-step instructions for testing Monit's capabilities as a PID 1 replacement in a Docker container, with a focus on making it accessible for Docker beginners.
-
Install Docker
- For macOS: Docker Desktop
- Download Docker Desktop from https://desktop.docker.com/mac/main/arm64/Docker.dmg for macOS with Apple Silicon
- For Intel Macs, use https://desktop.docker.com/mac/main/amd64/Docker.dmg
- Install the application by dragging it to your Applications folder
- For Linux: Docker Engine
- For Windows: Docker Desktop with WSL2
- For macOS: Docker Desktop
-
Clone or download the test repository
- Ensure you have the
monit-docker-testdirectory containing all necessary files:- Dockerfile
- monitrc
- scripts/program.sh
- scripts/process.sh
- scripts/check_zombies.sh
- Ensure you have the
Open Terminal and navigate to your test directory:
cd monit-docker-testBuild the Docker image with the following command:
docker build --no-cache -t monit-test .This creates a Docker image named "monit-test" containing Monit and all necessary test scripts. The --no-cache flag ensures a fresh build.
Note: This builds Monit from source in the container for testing purposes. See the NOTE in the Dockerfile for recommended production use.
Remove any existing containers with the same name:
docker rm -f monit-container 2>/dev/null || trueStart a new container:
docker run -d --name monit-container -p 2812:2812 monit-testThis runs the container in detached mode (-d), names it "monit-container", and maps port 2812 for Monit's web interface.
docker exec -it monit-container ps -p 1 -o comm=You should see monit as the output, confirming Monit is running as PID 1.
docker exec -it monit-container /usr/local/bin/check_zombies.shThis runs the check_zombies.sh script inside the container, which provides information about the container's processes and checks for zombie processes.
Create some short-lived processes and check if they become zombies:
docker exec -it monit-container bash -c 'for i in {1..10}; do (sleep 1 && exit) & done; sleep 3; ps -eo stat,pid,ppid,cmd | grep -c "^Z"'The output should be 0 if Monit is properly reaping processes.
Kill the monitored process and verify that Monit restarts it:
docker exec -it monit-container bash -c 'kill $(cat /tmp/process.pid); sleep 5; ps ax | grep process.sh'You should see that process.sh is running again after being killed.
docker exec -it monit-container monit summaryThis shows the status of all services monitored by Monit.
Verify that Monit has minimal resource overhead as PID 1:
docker exec -it monit-container bash -c 'ps -o pid,pcpu,pmem,rss,cmd -p 1'You should see low CPU and memory usage for the Monit process.
Open a browser and go to:
- http://localhost:2812 (for monit-container)
Stop the container to test Monit's shutdown handling:
docker stop monit-containerCheck the logs to verify proper shutdown:
docker logs monit-container | grep -E "shutdown|stopped|performing|responsibilities"You should see messages indicating that Monit recognized it was running as PID 1 and performed shutdown responsibilities.
When finished testing:
docker stop monit-container
docker rm monit-container
docker rmi monit-testYour test is successful if:
- Monit is running as PID 1: Confirmed in Step 3
- No zombie processes: Verified in Steps 4 and 5
- Process monitoring works: Processes restart when killed as seen in Step 6
- Clean shutdown: Proper signal handling during container termination in Step 10
- Resource efficiency: Low resource usage as observed in Step 8
If the container stops immediately:
- Check container logs:
docker logs monit-container - Verify file permissions within the container
- Validate the monitrc file:
docker exec -it monit-container monit -t
If zombie processes are detected:
- Run
docker exec -it monit-container ps -eo stat,pid,ppid,cmdto see details - Check if Monit eventually reaps them after a few seconds