Multi-service containers

Multi-service containers are a particularly tricky topic to broach, as the whole notion and recommended use of Docker is that you are only running single-process services within the container. Because of that, there is quite a bit of implicit pressure not to cover this topic because it can easily be misused and abused by developers who do not understand the reasons why this practice is strongly discouraged.

However, with that said and out of the way, there will be times where you will need to run multiple processes in a tight logical grouping where a multi-container solution would not make sense or it would be overly kludgey, which is why this topic is still important to cover. Having said all that, I cannot stress enough that you should only use this type of service collocation as a last resort.

Before we even write a single line of code, we must discuss an architectural issue with multiple processes running within the same container, which is called the PID 1 problem. The crux of this issue is that Docker containers run in an isolated environment in which they do not get help from the host's init process in reaping orphaned child processes. Consider an example process Parent Process, that is a basic executable that starts another process called Child Process, but as some point after that, if the associated Parent Process exits or is killed you will be left with the zombie Child Process loitering around in your container since Parent Process is gone and there is no other orphan reaping process running within the container sandbox. If the container exits, then the zombie processes will get cleaned up because they are all wrapped in a namespace, but for long-running tasks this can present a serious problem for running multiple processes inside a single image.

Terminology here might be confusing, but what was meant in simple terms is that every process is supposed be removed (also known as reaped) from the process table after it exits, either by the parent process or some other designated process (usually init) in the hierarchy that will take ownership of of it in order to finalize it. A process that does not have a running parent process in this context is called an orphan process.

Some tools have the ability to reap these zombie processes (such as Bash and a few other shells), but even they aren't good enough init processes for our containers because they do not pass signals such as SIGKILL, SIGINT, and others to child processes, so stopping the container or pressing things such as Ctrl + C in the Terminal are of no use and will not terminate the container. If you really want to run multiple processes inside the container, your launching process must do orphan reaping and signal passing to children. Since we don't want to use the full init system like systemd from the container, there are a couple of alternatives here, but in the recent versions of Docker we now have the --init flag, which can run our containers with a real init runner process.

Let's see this in action and try to exit a program where the starting process is bash:

$ # Let's try to run 'sleep' and exit with <Ctrl>-C
$ docker run -it
ubuntu
bash -c 'sleep 5000'
^C^C^C^C^C^C^C^C^C^C
<Ctrl-C not working>

$ # On second terminal
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
c7b69001271d ubuntu "bash -c 'sleep 5000'" About a minute ago Up About a minute

$ # Can we stop it?
$ docker stop c7b69001271d
<nothing happening>
^C

$ # Last resort - kill the container!
$ docker kill c7b69001271d
c7b69001271d

This time, we'll run our container with the --init flag:

$ docker run -it 
--init
ubuntu
bash -c 'sleep 5000'
^C

$ # <Ctrl>-C worked just fine!

As you can see, --init was able to take our signal and pass it to all the listening children processes, and it works well as an orphan process reaper, though the latter is really hard to show in a basic container. With this flag and its functionality, you should now be able to run multiple processes with either a shell such as Bash or upgrade to a full process management tool such as supervisord (http://supervisord.org/) without any issues.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset