Synchronizing docker containers with netcat
Sep 18, 2020
A user in /r/docker asked "How can i wait for container to exit with code 1 before starting another container using docker-compose". Ignoring the question of "why?" (a fair question, but let's assume a valid use case), one response was "use a shared volume and write the exit code to a file". Not a terrible solution, shared volumes are quite useful. However, I realized this was a great use of the somewhat-standard netcat
, so whipped up a sample compose file for fun.
Here's a simple compose file with two containers: second
that starts a netcat server on port 3000 that will return "OK" on connect, then print the message (cat
, this is where any logic based on the exit code would go) and run our desired workload. first
runs our first workload (sleep for five seconds) then opens a connection to second
, passing the exit code. Note that there's a few versions of netcat
out there, but I think this basic usage is the same between them.
version: '3'
services:
second:
image: alpine
command:
- '/bin/sh'
- '-c'
- 'echo "OK" | nc -l -p 3000 | cat && echo "doing the second thing"'
first:
image: alpine
command:
- '/bin/sh'
- '-c'
- 'echo "doing the first thing" && sleep 5 && echo "$$?" | nc second 3000'
Output:
) docker-compose up
Recreating container_wait_second_1 ... done
Recreating container_wait_first_1 ... done
Attaching to container_wait_second_1, container_wait_first_1
first_1 | doing the first thing
second_1 | 0
first_1 | OK
second_1 | doing the second thing
container_wait_first_1 exited with code 0
container_wait_second_1 exited with code 0
A neat variation on this is to use the -e
argument (in this version of netcat
anyways) to have netcat
run the workload, and send the stdout back to first
. diff:
- - 'echo "OK" | nc -l -p 3000 | cat && echo "doing the second thing"'- + - 'nc -l -p 3000 -e echo "doing the second thing"'
output:
) docker-compose -f docker-compose.passback.yml up
Recreating container_wait_second_1 ... done
Starting container_wait_first_1 ... done
Attaching to container_wait_first_1, container_wait_second_1
first_1 | doing the first thing
first_1 | doing the second thing
container_wait_first_1 exited with code 0
container_wait_second_1 exited with code 0