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