I’m trying to write a wrapper over Docker to propagate signals and standard output in a sensible way. First, Docker doesn’t handle SIGPIPE nicely:
$ docker run --rm ubuntu yes | head
y
y
y
y
y
y
y
y
y
y
write /dev/stdout: broken pipe
$
The extra output “write /dev/stdout: broken pipe” would be fine even if a little annoying, but the Dockerized process isn’t stopped. I wrote a wrapper to mount a FIFO as a volume and redirect the command’s standard output:
fifo=`basename $0`.$$
mkfifo $fifo
cat $fifo &
docker run --rm ubuntu sh -c "$* >$fifo"
rm $fifo
This does what I’m hoping for standard output; however, now, ctrl-C won’t stop the container. Apparently the shell won’t send SIGINT to the foreground child. I expected the following to work around this latest issue:
trap 'kill $!' INT TERM
fifo=`basename $0`.$$
mkfifo $fifo
cat $fifo &
docker run --rm ubuntu sh -c "$* >$fifo" &
wait
rm $fifo
However, on ctrl-C, the script exits, with the Dockerized process (and cat) continuing to spray output on my terminal.
Is it clear what I’m trying to do? I’m a big fan of UNIX workflow, but a lot of modern projects are depending on Docker (to do what the OS should already be doing). More specifically, I’m trying to benchmark a few Docker applications that are using a shared resource. I’d like to terminate one instance once it has output a certain number of lines and terminate all the other instances by sending SIGTERM.