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,变成一个帮你定位问题的好线索。