【docker】docker compose ls指令解读

docker compose ls指令解读

  • [一、docker compose ls 读的究竟是什么?](#一、docker compose ls 读的究竟是什么?)
  • 三、那个"restarting"状态在告诉你什么?
    • [3.1 定位问题容器](#3.1 定位问题容器)
    • [3.2 看日志,听容器"临终遗言"](#3.2 看日志,听容器“临终遗言”)
    • [3.2 深入检查](#3.2 深入检查)
  • [四、更优雅的开机自启:systemd 加持](#四、更优雅的开机自启:systemd 加持)
  • 五、写在最后

一、docker compose ls 读的究竟是什么?

很多人以为 docker compose ls 会去扫描硬盘上的 yaml 文件,像 docker ps 那样,只是按目录分类展示。其实不是。它根本不读文件,而是通过 Docker 守护进程查询运行中的容器,读取容器上的标签(label)。

每次你运行 docker compose up,Docker 都会悄悄地在容器上打几个特殊标签:

  • com.docker.compose.project:项目名

  • com.docker.compose.config-file:使用的配置文件路径

  • com.docker.compose.service:所属服务名

docker compose ls 就靠这些标签来分组、统计状态,并把当时使用过的 config file 显示出来。所以它展示的,是"曾经用 Compose 启动且现在还在跑的容器集合",而不是"你有哪些 yaml 文件"。文件删了也没关系,只要容器还活着,记录就还在。

这意味着什么呢?意味着如果你想给系统添加一个新项目,并不需要去某个注册中心登记------只需在那个目录下执行 docker compose up -d,或者用 -f 随意指定路径启动。启动那一刻,标签就写进了容器,从此会被 ls 识别。

二、重启后的"失忆"与"记忆"

开发环境里,你随手一个 docker compose up,服务跑得欢。可一旦服务器重启,这欢快就戛然而止------所有容器都没了,或者停在那里不动。为什么?因为 docker compose up 默认不会给容器加开机自启策略。它只负责把容器创建起来,至于宿主机重启之后要不要自动拉起来,它不管。

要让容器拥有"记忆",需要给它配置 restart 策略。在你的 docker-compose.yml 里,每个服务都可以加上:

复制代码
services:
  your-service:
    restart: always
  • always:无论什么原因退出,只要 Docker 服务在跑,就会自动重启容器。服务器重启后,Docker 一启动,这些容器也会跟着醒来。

  • unless-stopped:和 always 类似,但如果你手动执行了 docker compose stop,重启后就不会再自动启动。适合需要临时维护的场景。

加完策略后,务必用 --force-recreate 重建容器,因为重启策略在容器创建时就固定了:

复制代码
docker compose -f /path/to/docker-compose.yml up -d --force-recreate

现在再重启服务器试试------那些服务会自动站起来的。

三、那个"restarting"状态在告诉你什么?

既然有了重启策略,有时候你会看到 docker compose ls 的状态列里出现 restarting(1)。这其实是一个红色预警:某个容器在反复启动、崩溃、再启动的死循环中。

这种情况多半不是因为重启策略不对,而是容器内部出了问题:依赖的服务没就绪、配置文件有误、端口冲突、资源不足......因为策略是 always,Docker 只能忠实地不断尝试拉它起来,于是就出现了"挣扎"。

排查这类问题其实有固定套路:

3.1 定位问题容器

复制代码
docker compose -f /path/docker-compose.yml ps

找到状态为 restarting 的那个服务名。

3.2 看日志,听容器"临终遗言"

复制代码
docker compose -f /path/docker-compose.yml logs <服务名>

往往错误信息就写在这里------可能是一个 panic,也可能是一个连接超时。

3.2 深入检查

用 docker inspect <容器ID> 看看 ExitCode、健康检查、挂载卷等细节。

一个常见的"重启循环"是数据库还没准备好,应用就急着去连接。这时候可以给应用加上 depends_on,并配合健康检查,或者干脆让应用自带的 retry 机制去处理。记住:restart 只是保底手段,真正的稳健需要逻辑层面的容错。

四、更优雅的开机自启:systemd 加持

除了容器内的重启策略,如果你希望更精细地控制整个 compose 项目(比如开机启动顺序、关机时先停某些服务),可以用 systemd 来管理 Compose 本身。

创建一个 systemd 服务文件,例如 /etc/systemd/system/myapp.service:

复制代码
[Unit]
Description=My Docker Compose App
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
StandardOutput=journal

[Install]
WantedBy=multi-user.target

然后启用它:

复制代码
sudo systemctl enable myapp.service

这样,操作系统一启动,就会自动执行 docker compose up -d,关机时执行 down。你的整个应用栈会像系统服务一样被管起来,查看日志用 journalctl,状态用 systemctl status,统一又规范。

五、写在最后

Docker Compose 已经是开发者桌面上和服务器里必不可少的工具,但很多人还是习惯把它当"一次性"启动器来用。稍微多了解一点它的标签机制、重启策略和进程管理技巧,就能让服务从"靠人拉"变成"自己站"。

下次重启服务器,别再手动跑十几个 docker compose up 了。加一行 restart: always,或写一个 systemd unit,让你的容器学会记住自己该在什么时候醒来。而那个 restarting 的红色提示,也会从一个令人心烦的 bug,变成一个帮你定位问题的好线索。