Specify the versions of the softwares you install on your server

I was encountering the following error:

Building nginx-proxy
[+] Building 0.9s (8/8) FINISHED                                                                                                                                                                                                                               docker:default
 => [internal] load build definition from Dockerfile                                                                                                                                                                                                                     0.0s
 => => transferring dockerfile: 160B                                                                                                                                                                                                                                     0.0s
 => [internal] load metadata for docker.io/nginxproxy/nginx-proxy:latest                                                                                                                                                                                                 0.8s
 => [internal] load .dockerignore                                                                                                                                                                                                                                        0.0s
 => => transferring context: 2B                                                                                                                                                                                                                                          0.0s
 => [1/3] FROM docker.io/nginxproxy/nginx-proxy:latest@sha256:00b9708471c5e08beff200c6f78ff3471c7bf6332dbcfedf7ef55b8151d64148                                                                                                                                           0.0s
 => [internal] load build context                                                                                                                                                                                                                                        0.0s
 => => transferring context: 94B                                                                                                                                                                                                                                         0.0s
 => CACHED [2/3] COPY vhost.d/default /etc/nginx/vhost.d/default                                                                                                                                                                                                         0.0s
 => CACHED [3/3] COPY custom.conf /etc/nginx/conf.d/custom.conf                                                                                                                                                                                                          0.0s
 => exporting to image                                                                                                                                                                                                                                                   0.0s
 => => exporting layers                                                                                                                                                                                                                                                  0.0s
 => => writing image sha256:6d9fc6ed595c74653aa5f5505f8627111612d060eb8e8d82ff8e4c5fc453ddca                                                                                                                                                                             0.0s
 => => naming to docker.io/library/crud_in_the_cloud_nginx-proxy                                                                                                                                                                                                         0.0s
crud_in_the_cloud_db_1 is up-to-date
Recreating crud_in_the_cloud_django-app_1 ...
crud_in_the_cloud_pgadmin4_1 is up-to-date
Recreating crud_in_the_cloud_fastapi-api_1 ...

ERROR: for crud_in_the_cloud_django-app_1  'ContainerConfig'

ERROR: for crud_in_the_cloud_fastapi-api_1  'ContainerConfig'

ERROR: for django-app  'ContainerConfig'

ERROR: for fastapi-api  'ContainerConfig'
Traceback (most recent call last):
  File "/usr/bin/docker-compose", line 33, in <module>
    sys.exit(load_entry_point('docker-compose==1.29.2', 'console_scripts', 'docker-compose')())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 81, in main
    command_func()
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 203, in perform_command
    handler(command, command_options)
  File "/usr/lib/python3/dist-packages/compose/metrics/decorator.py", line 18, in wrapper
    result = fn(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 1186, in up
    to_attach = up(False)
                ^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 1166, in up
    return self.project.up(
           ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/project.py", line 697, in up
    results, errors = parallel.parallel_execute(
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/parallel.py", line 108, in parallel_execute
    raise error_to_reraise
  File "/usr/lib/python3/dist-packages/compose/parallel.py", line 206, in producer
    result = func(obj)
             ^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/project.py", line 679, in do
    return service.execute_convergence_plan(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/service.py", line 579, in execute_convergence_plan
    return self._execute_convergence_recreate(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/service.py", line 499, in _execute_convergence_recreate
    containers, errors = parallel_execute(
                         ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/parallel.py", line 108, in parallel_execute
    raise error_to_reraise
  File "/usr/lib/python3/dist-packages/compose/parallel.py", line 206, in producer
    result = func(obj)
             ^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/service.py", line 494, in recreate
    return self.recreate_container(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/service.py", line 612, in recreate_container
    new_container = self.create_container(
                    ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/service.py", line 330, in create_container
    container_options = self._get_container_create_options(
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/service.py", line 921, in _get_container_create_options
    container_options, override_options = self._build_container_volume_options(
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/service.py", line 960, in _build_container_volume_options
    binds, affinity = merge_volume_bindings(
                      ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/service.py", line 1548, in merge_volume_bindings
    old_volumes, old_mounts = get_container_data_volumes(
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/compose/service.py", line 1579, in get_container_data_volumes
    container.image_config['ContainerConfig'].get('Volumes') or {}
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
KeyError: 'ContainerConfig'
root@crudinthecloud:~/crud_in_the_cloud#

This error happened when I tried to run the following command on my server:

docker-compose -f docker-compose-prod.yml up -d --build

The error did not occur on the first build but on the second when I update the project, example after pulling new code and rebuilding.

After few attempt at fiddling with docker and docker compose by removing, rebuilding reading the logs, I decided to check the docker-compose's current version.

cruder@crudinthecloud:~/crud_in_the_cloud# docker --version Docker version 27.4.1, build b9d17ea cruder@crudinthecloud:~/crud_in_the_cloud# docker-compose --version docker-compose version 1.29.2, build unknown cruder@crudinthecloud:~/crud_in_the_cloud#

NO! I don't know the exact current version of every tool I use!! đŸ™ˆ

Realising that the version of the Docker-Compose that I installed while building the server is...old.

I updated it:

# Remove old version
sudo rm /usr/bin/docker-compose

# Download new version
sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Make it executable
sudo chmod +x /usr/local/bin/docker-compose

# Create symlink
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

# Verify new version
docker-compose --version
Docker Compose version v2.24.5

The issue could have been prevented by specifying the installation of a more recent version of Docker Compose in my Terraform configuration. Instead of using apt-get install -y docker-compose, which installed an older version from Ubuntu's repositories, I should have installed a newer version directly from Docker's GitHub releases.

The section of my Terraform config that introduced the issue:

...

resource "hcloud_server" "crud_in_the_cloud" {
  name         = "crudinthecloud"
  server_type  = "cpx21"
  location     = "nbg1"
  image        = "ubuntu-24.04"
  ssh_keys     = [data.hcloud_ssh_key.crud_in_the_cloud_ssh_key.id]
  firewall_ids = [hcloud_firewall.web_server_and_ssh.id]

  network {
    network_id = hcloud_network.crud_in_the_cloud_private_network.id
  }

  depends_on = [
    hcloud_network_subnet.crud_in_the_cloud_private_network_subnet
  ]

  # Pre-install Docker using user_data
  user_data = <<-EOF
              #!/bin/bash
              # Update the package list
              apt-get update

              # Install required packages
              apt-get install -y \
                  ca-certificates \
                  curl \
                  gnupg

              # Add Docker's official GPG key
              install -m 0755 -d /etc/apt/keyrings
              curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
                  gpg --dearmor -o /etc/apt/keyrings/docker.gpg
              chmod a+r /etc/apt/keyrings/docker.gpg

              # Set up the repository
              echo \
                  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
                  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

              # Install Docker
              apt-get update
              apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

              # Install docker-compose
              apt-get install -y docker-compose

              # Start Docker service
              systemctl start docker
              systemctl enable docker

              # Add user to docker group
              usermod -aG docker ubuntu
              newgrp docker
              EOF
}

So I replaced this line:

# Install docker-compose
apt-get install -y docker-compose

With:

# Install docker-compose v2
DOCKER_COMPOSE_VERSION="v2.24.5"
curl -L "https://github.com/docker/compose/releases/download/$${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

I use ln -sf instead of ln -s to ensure the symlink is created even if it already exists

I assumed that the docker-compose version installed in through Terraform config would be the the latest version

I should have specified the version explicitly since the repository packages might not be up-to-date.