Bootstrapping and monitoring multiple processes in Docker using monit
If you have every tried to start a docker container and keep it running, you must have encountered the problem that this is no easy task. Most stuff I like to start in container are things like http servers, application servers and various other middleware components which tend to have start scripts that daemonize the program. Starting a single process is a pain, starting multiple processes becomes nasty. My advise is to use monit to start all but the most simple Docker application containers! When I found monit while delving through the inner works Cloud Foundry, I was ecstatic about it! It was so elegant, small, fast, with a beautiful DSL that I thought it was the hottest thing since sliced bread! I was determined to blog it off the roof tops. Until.... I discovered that the first release dated from somewhere in 2002. So it was not hot and new; Clearly I had been lying under a UNIX rock for quite a while. This time, the time was right to write about it! Most of the middleware components I want to start in a docker container, have a habit to start the process, daemonize it and exit immediately, with the docker container on its tail. My first attempt to circumvent this while starting a tomcat server in Docker looked something like this:
/bin/bash -c "service tomcat7 start;while service tomcat7 status;do sleep 1;done
Quite horrific. Imaging the ugliness when you have to start multiple processes. A better solution is needed: With the zabbix docker container the problem was solved using simplevisor. As you can read in this post that was not a pleasant experience either. As I knew little about simplevisor and could not solve the problem, I put in an issue and resorted to a plain installation. But a voice in my head started nagging: "Why don't you fix it and send a pull request?" (actually, it was the voice of my colleague Arjan Molenaar). Then, I remembered from my earlier explorations to the inner workings of Cloud Foundry, a tool that would be really suitable for the job: monit. Why? It will:
- Give you a beautiful,readable specification file stating which processes to start
- Make sure that your processes will keep on running
- Deliver you a clean and crisp monitoring application
- Reduce all your Docker starts to a single command!
In the case of the Zabbix server there were seven processes to start: the zabbix server, agent, java agent, apache, mysql and sshd. In monit this looks as follows:
check process mysqld with pidfile /var/run/mysqld/mysqld.pid start program = "/sbin/service mysqld start" stop program = "/sbin/service mysqld stop" check process zabbix-server with pidfile /var/run/zabbix/zabbix_server.pid start program = "/sbin/service zabbix-server start" stop program = "/sbin/service zabbix-server stop" depends on mysqld check process zabbix-agent with pidfile /var/run/zabbix/zabbix_agentd.pid start program = "/sbin/service zabbix-agent start" stop program = "/sbin/service zabbix-agent stop" check process zabbix-java-gateway with pidfile /var/run/zabbix/zabbix_java.pid start program = "/sbin/service zabbix-java-gateway start" stop program = "/sbin/service zabbix-java-gateway stop" check process httpd with pidfile /var/run/httpd/httpd.pid start program = "/sbin/service httpd start" stop program = "/sbin/service httpd stop" depends on zabbix-server check process sshd with pidfile /var/run/sshd.pid start program = "/sbin/service sshd start" stop program = "/sbin/service sshd stop"
Normally when you start monit it will start as a daemon. But fortunately, you can prevent this with the following configuration.
Your Dockerfile CMD can now always look the same:
monit -d 10 -Ic /etc/monitrc
Finally, by adding the following statement to the configuration you get an application to view the status of your container processes,
set httpd port 2812 allow myuser:mypassword
After starting the container, surf to port 2812 and you will get a beautiful page showing the state of your processes and the ability to stop and restart them.
Just delve into the documentation of monit and you will find much more features that will allow you to monitor network ports and files, start corrective actions and send out alerts.
Monit is true to its UNIX heritage: it is elegant and promotes an autonomous monitoring system. Monit is cool!