A Docker container is usually dedicated to running one daemon process, such as Apache to serve a web application. If the application needs a cache, or a database, then the container running the application is linked to another containing running the cache, and yet another container running the database. However, what if we need (or want) to run several daemon applications inside the same single container?
The use case
While it is a kind of anti-pattern to run several daemons inside the same container, instead of running several containers for each daemon and then cross-linking them, it may be sometimes useful. A concrete example from the Invenio digital library software world: we would like to fully emulate what users get when they run e.g. Invenio v1.0.5 on a vanilla CentOS 5 server system. This means running then-available Python-2.4, with then-available version of MySQL-5.0 and then-available pre-packaged version of MySQL-python library.
Creating an Invenio docker image that relies on CentOS 5 and runs everything inside the same container will allow us to achieve this emulation. (Theoretically, we could create several CentOS 5 based docker images and linked containers, one for running the Apache, one for running the MySQL, etc. However, we may just as well run everything inside the same image, considering that we can use the same kick-start installation scripts to provision the box, and considering that providing support to older installations in this way is relatively rare.)
The technique
Let's assume then that we'd like to run an MUA daemon process such as Exim, a web server process such as Apache, and a database server process such as MySQL all inside the same CentOS 5 based container.
The trick to use supervisord and run the supervisord daemon that will take care of keeping all the other wanted daemons alive.
Here is a minimal Dockerfile to test the idea:
FROM centos:5 RUN yum install -y epel-release && \ yum update -y && \ yum install -y exim \ httpd \ mysql-server \ supervisor && \ yum clean all RUN /sbin/service mysqld start && \ mysqladmin -u root password '' RUN echo "[supervisord]" > /etc/supervisord.conf && \ echo "nodaemon=true" >> /etc/supervisord.conf && \ echo "" >> /etc/supervisord.conf && \ echo "[program:exim]" >> /etc/supervisord.conf && \ echo "command=/usr/sbin/exim -bd -q1h" >> /etc/supervisord.conf && \ echo "" >> /etc/supervisord.conf && \ echo "[program:mysqld]" >> /etc/supervisord.conf && \ echo "command=/usr/bin/mysqld_safe" >> /etc/supervisord.conf && \ echo "" >> /etc/supervisord.conf && \ echo "[program:httpd]" >> /etc/supervisord.conf && \ echo "command=/usr/sbin/apachectl -D FOREGROUND" >> /etc/supervisord.conf CMD ["/usr/bin/supervisord"]
Here is corresponding docker-compose.yml:
web: build: . command: /usr/bin/supervisord
The verification
Let us build the image and start the container:
$ docker-compose build $ docker-compose up web_1 | 2015-02-11 20:56:56,265 CRIT Supervisor running as root (no user in config file) web_1 | 2015-02-11 20:56:56,282 INFO supervisord started with pid 1 web_1 | 2015-02-11 20:56:56,283 INFO spawned: 'httpd' with pid 6 web_1 | 2015-02-11 20:56:56,284 INFO spawned: 'mysqld' with pid 7 web_1 | 2015-02-11 20:56:56,285 INFO spawned: 'exim' with pid 8 web_1 | 2015-02-11 20:56:57,282 INFO success: httpd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) web_1 | 2015-02-11 20:56:57,283 INFO success: mysqld entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) web_1 | 2015-02-11 20:56:57,285 INFO success: exim entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
Let us connect to the running container to confirm that the daemons are well up and running:
$ docker exec -i -t 6cc431e69c5f bash [root@6cc431e69c5f /]# ps aux | grep mysql root 7 0.1 0.0 10844 2168 ? S 20:56 0:00 /bin/sh /usr/bin/mysqld_safe mysql 83 0.3 0.3 188400 28532 ? Sl 20:56 0:00 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --pid-file=/var/run/mysqld/mysqld.pid --skip-external-locking --log-error=/var/log/mysqld.log --socket=/var/lib/mysql/mysql.sock root 105 0.0 0.0 61256 1792 ? S+ 20:57 0:00 grep mysql [root@6cc431e69c5f /]# ps aux | grep httpd root 10 0.0 0.0 174412 7076 ? S 20:56 0:00 /usr/sbin/httpd -D FOREGROUND apache 21 0.0 0.0 174544 3704 ? S 20:56 0:00 /usr/sbin/httpd -D FOREGROUND apache 22 0.0 0.0 174544 3704 ? S 20:56 0:00 /usr/sbin/httpd -D FOREGROUND apache 23 0.0 0.0 174544 3704 ? S 20:56 0:00 /usr/sbin/httpd -D FOREGROUND apache 24 0.0 0.0 174544 3704 ? S 20:56 0:00 /usr/sbin/httpd -D FOREGROUND apache 25 0.0 0.0 174544 3704 ? S 20:56 0:00 /usr/sbin/httpd -D FOREGROUND apache 26 0.0 0.0 174544 3704 ? S 20:56 0:00 /usr/sbin/httpd -D FOREGROUND apache 27 0.0 0.0 174544 3704 ? S 20:56 0:00 /usr/sbin/httpd -D FOREGROUND apache 28 0.0 0.0 174544 3704 ? S 20:56 0:00 /usr/sbin/httpd -D FOREGROUND root 107 0.0 0.0 61256 1884 ? S+ 20:57 0:00 grep httpd [root@6cc431e69c5f /]# ps aux | grep exim exim 8 0.0 0.0 79924 6388 ? S 20:56 0:00 /usr/sbin/exim -bd -q1h