Fixing docker-compose stalled containers

August 24, 2024

This is the first post after almost two years. Yay! I've been busy with various projects and gigs, and I'm hoping I'll have a chance to write about them in future. But for now, let's focus on my issue with docker-compose.

First of all, let's check my setup:

  1. I'm running vanilla docker (sorry, no podman yet in my books).
  2. Docker runtime is crun.

Here is the problem: when I run docker-compose yaml file with multiple containers with docker-compose up and hit Ctrl-c to stop everything at some point, docker-compose can miss some containers. And running docker-compose up again will usually yield this error:

ERROR: for <some-container> 'ContainerConfig'
Traceback (most recent call last):
  File "docker-compose", line 3, in <module>
  File "compose/cli/main.py", line 81, in main
  File "compose/cli/main.py", line 203, in perform_command
  File "compose/metrics/decorator.py", line 18, in wrapper
  File "compose/cli/main.py", line 1186, in up
  File "compose/cli/main.py", line 1182, in up
  File "compose/project.py", line 702, in up
  File "compose/parallel.py", line 108, in parallel_execute
  File "compose/parallel.py", line 206, in producer
  File "compose/project.py", line 688, in do
  File "compose/service.py", line 581, in execute_convergence_plan
  File "compose/service.py", line 503, in _execute_convergence_recreate
  File "compose/parallel.py", line 108, in parallel_execute
  File "compose/parallel.py", line 206, in producer
  File "compose/service.py", line 496, in recreate
  File "compose/service.py", line 615, in recreate_container
  File "compose/service.py", line 334, in create_container
  File "compose/service.py", line 922, in _get_container_create_options
  File "compose/service.py", line 962, in _build_container_volume_options
  File "compose/service.py", line 1549, in merge_volume_bindings
  File "compose/service.py", line 1579, in get_container_data_volumes
KeyError: 'ContainerConfig'
[30641] Failed to execute script docker-compose

To solve this, I wrapped up everything in a Makefile with a bash trap command. If you are unfamiliar with it, it will execute a command when the shell receives a signal. In my case, I want to capture Ctrl-c.

Here is the magic:

# Makefile example
.PHONY: start pull

pull:
	docker-compose pull

start:
	 trap 'docker-compose down' SIGINT; docker-compose up

SIGINT is interrupt from keyboard and that's usually Ctrl-c for bash. Now, every time I hit Ctrl-c after make start, it will run docker-compose down. Weird problems require hacky solutions, what to say ;)