1. 概述

Docker Compose 是管理多容器应用的利器。但在实际使用中,有时我们会遇到 docker-compose up 命令卡住、没有明确错误提示的问题,令人头疼。

此时,--verbose 选项就能派上用场。它能输出详细的启动日志,帮助我们更精准地定位问题根源。

本文将介绍 Docker Compose 启动失败的常见原因,并演示如何使用 --verbose 选项进行有效排查。

2. 理解 Docker Compose 启动问题

Docker Compose 启动失败会打断开发流程,甚至影响部署。在深入排查之前,我们先了解几个常见问题类型,以便在日志中识别它们。

2.1. 常见启动问题类型

启动过程卡住是最常见的问题之一。例如:

$ docker-compose up
Building app...

这种情况可能由 docker-compose.yml 配置错误、系统资源不足等原因引起。

构建失败也是常见问题。Docker 在构建镜像时可能会因为 Dockerfile 错误、路径错误或依赖缺失而失败,例如:

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

网络冲突也可能导致启动失败。比如多个容器或服务使用了相同端口或网络名,Docker Compose 就无法正常启动。

2.2. 详细日志的重要性

解决这些问题,仅靠模糊的错误提示是不够的。详细日志(即“verbose logs”)可以让我们看到 Docker Compose 启动时的完整流程。

例如,没有启用 verbose 时,网络冲突可能导致进程静默卡住。但启用后,你可能看到类似如下信息:

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

这直接指向了网络冲突,排查起来就容易得多。

可以说,verbose 日志就像放大镜,能帮助我们看清 Docker Compose 的内部流程,从而快速定位问题并修复。

3. 使用 --verbose 选项进行排查

现在我们已经了解了详细日志的价值,接下来介绍 --verbose 选项如何帮助我们高效排查问题。

3.1. --verbose 的作用

--verbose 选项能显著增强 docker-compose up 命令输出的信息量。标准模式只显示基础信息,而启用 verbose 后,我们可以看到:

  • 网络创建过程
  • 卷挂载情况
  • 与 Docker Daemon 的交互等

这些信息对排查启动卡顿、构建失败或网络问题非常有帮助。

理解这些日志,能节省大量排查时间。

3.2. 使用 --verbose 示例

进入 docker-compose.yml 所在目录后,运行:

$ 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.
...

如你所见,--verbose 会输出容器创建、服务启动、依赖加载等详细过程,帮助我们追踪问题。

提示:如果你想强制重建镜像,可以加上 --build 参数:

$ docker-compose --verbose up --build

这样即使本地已有缓存镜像,也会重新构建一次,确保使用的是最新代码。

4. 常见问题及解决方案

有了 --verbose 的加持,我们可以更高效地排查以下常见问题。

4.1. 系统熵不足

系统熵(Entropy)是指操作系统中随机性资源的多少。在虚拟化环境中,熵不足可能导致 Docker Compose 卡住,特别是在生成容器名等需要随机性的操作时。

你可以通过以下命令查看当前系统可用熵:

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

如果输出值小于 1000,说明熵不足,这可能是导致启动卡顿的原因之一。

解决方案:安装 haveged 工具,它能生成额外的熵以缓解这个问题:

$ sudo apt-get install haveged

安装后,haveged 会在后台运行,持续补充系统熵,减少卡顿问题。

4.2. 构建上下文过大

构建上下文(Build Context)包含所有 Docker 构建镜像所需的文件。如果这个上下文过大,可能会导致构建过程变慢甚至卡住。

优化方法:使用 .dockerignore 文件排除不必要的文件和目录。其语法与 .gitignore 类似。

例如,如果你的项目中不需要 node_modules,可以在 .dockerignore 中添加:

node_modules

这样 Docker 在构建时就不会把 node_modules 打包进上下文,提升构建效率。

4.3. 网络冲突

当多个 Docker 网络使用相同名称,或与主机上的其他进程发生网络冲突时,Docker Compose 就无法正常启动。

你可以用以下命令列出当前所有 Docker 网络:

$ 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

如果发现有重复或不再使用的网络,可以用以下命令删除:

$ docker network rm <network_id>

清理冲突网络后,Docker Compose 就能顺利创建所需网络,服务也能正常启动。

4.4. 端口冲突

docker-compose.yml 中指定的端口已被其他进程占用时,Docker Compose 无法绑定该端口,导致容器启动失败。

你可以用以下命令查看正在运行的容器及其端口映射:

$ 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

如果发现某个端口被占用了,可以选择:

  • 停止占用端口的容器:
$ docker stop <container_id>
  • 或者修改 docker-compose.yml,使用一个未被占用的端口。

5. 总结

本文介绍了如何使用 --verbose 选项排查 Docker Compose 启动问题。通过启用该选项,可以获得更详细的日志输出,帮助我们快速识别并解决以下常见问题:

  • 系统熵不足导致的启动卡顿
  • 构建上下文过大导致的构建缓慢
  • 网络名称冲突
  • 端口被占用导致的启动失败

建议:遇到 Docker Compose 启动问题时,第一时间加上 --verbose 查看详细日志,能节省大量排查时间。

⚠️ 注意:虽然 --verbose 输出的信息量大,但也不建议长期开启,避免日志过多影响可读性。

掌握 --verbose 的使用,能让你在处理容器编排问题时更加游刃有余。


原始标题:Troubleshooting docker-compose Startup Issues Using the –verbose Option