1

I would like to start two different services in my Docker container and exit the container as soon as one of them exits. I looked at supervisor, but I can't find how to get it to quit as soon as one of the managed applications exits. It tries to restart them up to three times, as is the standard setting and then just sits there doing nothing. Is supervisor able to do this or is there any other tool for this? A bonus would be if there also was a way to let both managed programs write to stdout, tagged with their application name, e.g.:

[Program 1] Some output
[Program 2] Some other output
[Program 1] Output again

RikuXan
  • 393
  • 5
  • 15
  • possible duplicate of [Can I run multiple programs in a Docker container?](http://stackoverflow.com/questions/19948149/can-i-run-multiple-programs-in-a-docker-container) – perror Sep 09 '15 at 06:31
  • @perror The question you linked is more of a "is it possible", while I'm asking "how can I do it exactly this way". Also, this question is almost two years old which is probably a lot of time in docker universe, seeing as it seems linking was just introduced when this question was asked and answered. – RikuXan Sep 09 '15 at 06:38

2 Answers2

2

Since you asked if there was another tool... we designed and wrote a powerful replacement for supervisord that is designed specifically for Docker. It automatically terminates when all applications quit, as well as has special service settings to control this behavior, plus will redirect stdout with tagged syslog-compatible output lines as well. It's open source, and being used in production.

Here is a quick start for Docker: http://garywiz.github.io/chaperone/guide/chap-docker-simple.html

There is also a complete set of tested base-images which are a good example at: https://github.com/garywiz/chaperone-docker, but these might be overkill and the earlier quickstart may do the trick.

Gary Wisniewski
  • 1,080
  • 10
  • 9
  • Thanks for you answer, chaperone looks really good and seems to tick all the boxes I need. Unfortunately, adding 230MB to the image by installing python3-pip really makes me thing about using it. In any images that already include python3 this would be a no-brainer, I'm not so sure in others though (The image I'm currently using has python2.7 installed, so supervisord only takes up about 2MB). – RikuXan Sep 10 '15 at 13:08
  • It's not actually python3-pip that adds 230MB to the image, it's the dependencies on the gcc build chain (which you can eliminate). For example the chaperone-alpinebase image (link above) is only 55MB (total), including the full OS distro, Python3+pip+chaperone. It's quite full featured and is a good case-study on how overly fat other images actually are. Even the ubuntu chaperone-baseimage is 345MB total. However, I take your point, and we are planning a .go version within the next few months. Thanks for the feedback, very much. – Gary Wisniewski Sep 10 '15 at 21:53
  • If you want to save a significant amount of space, use --no-install-recommends, as follows, you'll be surprised at the difference: "apt-get install --no-install-recommends -y python3-pip then "pip3 install chaperone". Since this seems like it may be a popular issue, I just added a small tutorial on how to create the smallest possible Chaperone-based images: http://garywiz.github.io/chaperone/guide/chap-docker-smaller.html – Gary Wisniewski Sep 11 '15 at 04:41
1

I found solutions to both of my requirements by reading through the docs some more.

Exit supervisord on application exit
This can be achieved by using a custom eventlistener. I had to add the following segment into my supervisord configuration file:

[eventlistener:shutdownevent]
command=/shutdownhandler.sh
events=PROCESS_STATE_EXITED

supervisord will start the referenced script and upon the given event being triggered (PROCESS_STATE_EXITED is triggered after the exit of one of the managed programs and it not restarting automatically) will send a line containing data about the event on the scripts stdin.
The referenced shutdownhandler-script contains:

#!/bin/bash
while :
do
    echo -en "READY\n"
    read line
    kill $(cat /supervisord.pid)
    echo -en "RESULT 2\nOK"
done

The script has to indicate being ready by sending "READY\n" on its stdout, after which it may receive an event data line on its stdin. For my use case upon receival of a line (meaning one of the managed programs has exited), a SIGTERM is sent to the supervisord process being found by the pid it leaves in its pid file (situated in the root directory by default). For technical completeness, I also included a positive answer for the eventlistener, though that one should never matter.

Tagged output on stdout
I did this by simply starting a tail process in the background before starting supervisord, tailing the programs output log and piping the lines through ts (from the moreutils package) to prepend a tag to it. This way it shows up via docker logs with an easy way to see which program actually wrote the line.

tail -fn0 /var/log/supervisor/program1.log | ts '[Program 1]' &
RikuXan
  • 393
  • 5
  • 15