1. Overview

Docker Compose is a helpful tool for managing multi-container applications. But sometimes, things don’t go as planned. We might find ourselves staring at a terminal where the docker-compose up command hangs without clear error messages.

However, the –verbose flag offers detailed insights into the startup process. This can help us pinpoint the cause of the problem.

In this tutorial, we’ll explore common reasons for these hangs and how to use the –verbose flag to troubleshoot effectively.

2. Understanding docker-compose Startup Issues

Docker Compose startup issues can disrupt our workflow and delay deployments. Before we jump into troubleshooting, let’s get familiar with some common culprits behind those frustrating Docker Compose startup problems.

Understanding these issues will help us recognize them when they appear in the verbose logs.

2.1. Common Startup Problems

One of the most common issues we can encounter with docker-compose up is a hanging process. In this case, running the command seems to freeze without any progress or error messages:

$ docker-compose up
Building app...

This can happen for various reasons, like misconfigurations in our docker-compose.yml file or resource constraints on our system.

Another frequent issue is failed builds. These occur when Docker Compose encounters problems while creating the images specified in our docker-compose.yml file. Errors in our Dockerfile, incorrect file paths, or missing dependencies can all contribute to build failures.

In such cases, we can encounter an error message:

ERROR: Service 'app' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder367230859/entrypoint.sh: no such file or directory

Lastly, network conflicts can also cause a startup issue. This happens when multiple containers or services try to use the same ports or network names, causing Docker Compose to stumble during startup.

2.2. Importance of Detailed Diagnostics

To solve these startup issues, we need more than just a vague error message. Detailed logs — often referred to as “verbose logs” — provide a ton of information about what’s happening behind the scenes during the Docker Compose startup process.

For example, without verbose logging, a network conflict might cause the process to hang silently. But with verbose logging enabled, we can see a more detailed error message:

ERROR: for app  Cannot start service app: driver failed programming external connectivity on endpoint ...

The message above points directly to the network conflict. This makes troubleshooting much easier.

Verbose logs act like a magnifying glass. These logs enable us to examine the inner workings of Docker Compose and identify the precise point of failure. With this knowledge, we can quickly diagnose the issue and apply the appropriate fix.

3. Using the –verbose Option for Troubleshooting

Now that we understand the importance of detailed diagnostics, let’s find out how the –verbose option empowers us to troubleshoot Docker Compose startup issues effectively.

3.1. The –verbose Option in docker-compose up

The –verbose option improves the information we get when running the docker-compose up command. While the standard command gives us a basic view, –verbose provides a much more detailed look at the startup process.

We get to see the exact actions Docker Compose is taking, like creating networks, setting up volumes, and communicating with the Docker daemon itself.

Consequently, we get access to extensive logs that can help diagnose issues like hanging processes, failed builds, or network problems.

Therefore, understanding these logs can save us a lot of time and effort in resolving startup issues.

3.2. Using the –verbose Option

Now that we understand the benefits of the –verbose flag, let’s see how to use it in practice.

First, let’s navigate to the directory where our docker-compose.yml file is located. Once we’re in the right directory, let’s execute the docker-compose –verbose up command:

$ docker-compose --verbose up
...
Attaching to app-1, mysql-1
DEBU[0115] otel error error="<nil>"
mysql-1 | 2024-08-21 18:07:45+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.39-1.el9 started.
mysql-1 | 2024-08-21 18:07:45+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
mysql-1 | 2024-08-21 18:07:45+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.39-1.el9 started.
mysql-1 | 2024-08-21 18:07:45+00:00 [Note] [Entrypoint]: Initializing database files
mysql-1 | 2024-08-21T18:07:45.651276Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
mysql-1 | 2024-08-21T18:07:45.651326Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.39) initializing of server in progress as process 80
app-1 | yarn install v1.22.19
mysql-1 | 2024-08-21T18:07:45.657550Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
...

With the –verbose option, Docker Compose starts our application in verbose mode. This provides details about each step of the process. As the containers are built, started, and connected, we see a stream of logs in our terminal. As a result, we get valuable insights into what’s happening behind the scenes.

Furthermore, to rebuild our images while using verbose mode, we can add the –build flag to the command:

$ docker-compose --verbose up --build

This command forces Docker Compose to rebuild the images, even if they already exist in our local cache. The –build option can be helpful when we’ve made changes to our Dockerfile or application code and want to ensure we’re using the latest version.

4. Common Issues and Solutions

Armed with the –verbose flag, we can now explore some common scenarios where Docker Compose might hang during startup. Let’s analyze these issues and their corresponding solutions.

4.1. Low System Entropy

System entropy is a measure of the randomness in an operating system. It plays a vital role in Docker Compose operations, especially within virtualized environments.

Docker Compose relies on this randomness for tasks like generating unique container names. When entropy levels are low, Docker Compose can hang while waiting for sufficient randomness.

Let’s see how to check our system’s entropy:

$ cat /proc/sys/kernel/random/entropy_avail

If the output is less than 1000, it’s a likely contributor to our startup issues. This problem is notably common in virtual machines, where hardware-generated randomness is limited.

A practical solution is to install haveged, a daemon that generates additional entropy:

$ sudo apt-get install haveged

Once installed, haveged runs in the background. Then, it continuously boosts our system’s entropy and minimizes the chances of Docker Compose hanging due to low randomness.

4.2. Large Build Contexts

Another common issue that can cause Docker Compose to hang is handling large build contexts. The build context encompasses all files and directories that Docker needs during the image build process.

If this context is too large, it can significantly slow down or even stall the build process.

To optimize this, we can create a .dockerignore file to exclude unnecessary files and directories from the build context. This file works similarly to a .gitignore file. It allows us to specify patterns for exclusion.

For example, if we have a node_modules directory in our project that’s not required for the image, we can add the following line to our .dockerignore file:

node_modules

Consequently, by streamlining our build context, Docker Compose will only process essential files. This results in faster and more efficient builds.

4.3. Network Conflicts

Network conflicts can occur when multiple Docker networks share the same name, or when a network name clashes with another process on our machine.

These conflicts can prevent Docker Compose from successfully starting up our services.

To identify any network conflict, we can list existing Docker networks:

$ docker network ls
NETWORK ID     NAME                    DRIVER    SCOPE
c756fed17ebb   bridge                  bridge    local
745a2fdb6296   docker_default          bridge    local
728c7a789bb5   emmanueloyibo_default   bridge    local
2bbd2cd84193   host                    host      local
242458fefd43   jenkins                 bridge    local
e4152a8945f6   minikube                bridge    local
4079d96de0b5   none                    null      local
81510159a653   projects_default        bridge    local

Moreover, if we find any unnecessary or duplicate networks, we can remove them:

$ docker network rm <network_id>

Resolving this conflict allows Docker Compose to create the necessary network environment without any issues, ensuring smooth service startups.

4.4. Port Conflicts

Port conflicts arise when a port specified in our docker-compose.yml file is already being used by another process on our host machine. Docker Compose will fail to start any container that tries to bind to an occupied port.

We can identify running containers and their port mappings using docker ps:

$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
5b9474139200   httpd     "httpd-foreground"       7 seconds ago   Up 6 seconds   0.0.0.0:81->80/tcp, :::81->80/tcp       httpd-container
d4e01d3132a8   nginx     "/docker-entrypoint.…"   9 minutes ago   Up 9 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   kind_newton

If there’s a conflict, we can stop the offending container:

$ docker stop <container_id>

Alternatively, we can modify our docker-compose.yml file to use a different, available port.

5. Conclusion

In this article, we’ve learned how the –verbose flag can be a valuable asset when Docker Compose encounters unexpected startup issues.

By providing detailed logs, the –verbose flag offers a clearer view into underlying processes. This makes it easier to pinpoint and fix common Docker Compose startup problems.