通过 curl 安装 Coolify 后面板打不开,先别反复重跑脚本:检查 Docker 守护进程、8000 端口监听和服务器防火墙;遇到 Deployment Failed,按 Compose 解析、镜像拉取、镜像构建和容器启动四层排查;容器 Exited 则看退出码和运行日志;域名返回 502、504 或 HTTPS 异常,再依次检查 DNS、网络入口、反向代理和容器端口。
| 看到的现象 | 优先检查 |
|---|---|
| 安装脚本报错或面板打不开 | Docker、8000 端口监听、防火墙、安全组 |
Deployment Failed |
部署日志、Compose 配置、镜像拉取 |
容器 Exited 或反复重启 |
容器状态、退出码、运行日志 |
| 域名 502 或超时 | DNS、目标端口、反向代理上游 |
| HTTPS 证书错误 | A/AAAA 记录、证书验证、80/443、TLS 握手 |
开始排障前先执行下面这些只读命令:
docker version
docker compose version
docker info
docker compose ps -a
其中,docker compose ps -a 要在正确的 Compose 项目目录执行。旧环境如果只提供 docker-compose,先确认实际可用命令。本文后文统一用 docker compose 表示 Compose 操作,实际执行时按环境使用对应语法,不要把两套语法混用。
Coolify 官方 GitHub 仓库将其定位为开源、可自托管的 Vercel、Heroku 与 Netlify 替代方案,可用于部署静态站点、数据库和全栈应用。 实际排障时,故障通常不在“能不能安装”这一层,而在配置、容器状态、网络入口和证书之间。
curl 脚本跑完了,8000 端口为什么还打不开
先判断安装是否完成、Docker 是否运行,以及 8000 端口链路是否被挡住,不要把重跑安装脚本当成通用修复方法。
安装前至少确认系统是 Linux,Docker 环境可用,并留出足够的存储和内存。现有资料没有给出统一的最低配置数值,因此不要把某台机器的规格当成所有部署的硬门槛。
安装示例使用下面的命令,安装完成后从服务器的 8000 端口进入配置。 脚本会检查当前用户是否具有 root 权限,因此也可以使用带 sudo 的写法。
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash
这条命令把下载和执行连在了一起。为了先审阅脚本内容,可以拆成两步:
curl -fsSL https://cdn.coollabs.io/coolify/install.sh -o install.sh
less install.sh
sudo bash install.sh
安装脚本会修改系统环境并启动相关服务,执行前至少应确认下载地址和脚本内容符合预期。不要因为下载缓慢,就直接换成来源不明的第三方替换脚本。
安装结束后,先看 Docker 是否真的可用:
docker version
docker info
df -h
free -h
在使用 systemd 的 Linux 发行版上,还可以检查 Docker 服务状态:
systemctl is-active docker
systemctl status docker --no-pager
接着确认 8000 端口是否监听:
ss -lntp | grep ':8000'
curl -v http://127.0.0.1:8000/ -o /dev/null
docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
按这些结果分流。如果 docker info 失败,说明 Docker 客户端可能存在,但守护进程没有正常响应,或者当前用户没有访问 Docker socket 的权限。如果 Docker 正常,但 ss 找不到 8000 端口,应回查安装输出和容器状态,不要继续检查域名。如果本机访问 127.0.0.1:8000 成功,但外部浏览器访问超时,优先检查云安全组、服务器防火墙和上游网络对 8000 端口的拦截。如果本机访问也失败,则说明问题还在服务器内部,应继续看容器状态和运行日志。
如果安装卡在镜像拉取,先区分 DNS、网络、镜像地址和 CPU 架构问题:
getent hosts registry-1.docker.io
curl -sS -o /dev/null -w '%{http_code}\n' https://registry-1.docker.io/v2/
docker pull <image>
能收到 HTTP 响应,至少说明到镜像仓库的网络路径已经建立;具体状态码还可能涉及认证或仓库策略。如果域名无法解析,是 DNS 问题;连接超时或被拒绝,是出口网络、防火墙或代理问题;镜像名或标签不存在,则是仓库地址问题;错误里出现架构不匹配、no matching manifest 一类信息时,再核对镜像是否提供当前服务器架构的版本。
现有资料把 Docker 镜像拉取列为国内安装时的主要卡点。 这可以作为排查方向,但不能据此认定所有超时都是同一个问题,也不要用一个未经核验的第三方安装脚本替换官方脚本。
Docker Compose 部署失败,先分清解析、拉取、构建还是启动
Compose 报错时,按配置解析、镜像获取、镜像构建、容器启动四层检查,不要在尚未定位时直接重装 Coolify。
下面用 compose.yaml 代表实际 Compose 文件路径,用 <service> 代表真实服务名。服务名可以先从下面的命令获取:
docker compose -f compose.yaml config --services
先验证 Compose 最终解析出来的配置:
docker compose -f compose.yaml config
这一步重点看镜像名称、构建上下文、环境变量、端口、网络、卷和健康检查是否与预期一致。Compose 在解析文件时会进行变量插值,缺失变量、变量名大小写不一致、.env 不在预期位置,都可能得到空值或错误配置。支持相关选项的 Compose 版本还可以先查看未插值的结构:
docker compose -f compose.yaml config --no-interpolate
.env 主要用于给 Compose 插值,它不会因为文件存在就自动进入容器。容器里能否读到变量,仍取决于 environment 或 env_file 配置。也可以显式指定变量文件:
docker compose --env-file .env -f compose.yaml config
某些仓库会把环境变量模板命名为 env.windows-docker-desktop.example。现有资料记录过将这个文件改名为 .env 后再部署的场景,但这是特定项目的做法,不是所有 Compose 项目的统一要求;是否改名应以仓库说明为准。
配置解析通过后,再分别检查镜像拉取和镜像构建:
docker compose -f compose.yaml pull
docker compose -f compose.yaml build
pull 主要暴露镜像名、标签、网络、认证和架构问题;它只适用于引用远端镜像的服务。build 主要暴露 Dockerfile 路径、构建上下文、依赖下载和构建参数问题。两者都成功,也不代表应用一定能启动。
接下来看服务和日志:
docker compose -f compose.yaml ps -a
docker compose -f compose.yaml logs --tail=200 --timestamps <service>
如果服务没有创建成功,先查 Coolify 部署日志和上面的拉取、构建输出。如果容器创建后立即退出,再查应用运行日志。此时还应检查宿主机端口是否已被占用、挂载目录权限是否正确、依赖服务是否已经可用,以及健康检查命令本身是否能在容器环境里运行。
在 Coolify 已经管理的同一项目上,不要随手再执行另一套 up -d:
docker compose -f compose.yaml up -d
它可能创建重复容器、网络或卷,让 Coolify 页面与宿主机实际状态变得不一致。只在仓库副本或隔离测试环境中使用这条命令。
容器显示 Exited,部署日志里却找不到原因
部署日志负责解释“容器如何被创建”,容器日志负责解释“进程为什么退出”,两者不能混用。
先找到目标容器及其状态:
docker compose -f compose.yaml ps -a
docker inspect --format '{{json .State}}' <container_id>
docker logs --tail 200 --timestamps <container_id>
按这些结果继续排查。如果没有容器,问题还在拉取、构建或部署阶段,应回到 Coolify 部署日志。如果容器刚创建就退出,退出码、stdout 和 stderr 通常比最后一条 UI 提示更有用。如果容器反复重启,则检查启动命令、依赖服务、挂载是否在启动前准备好,以及健康检查是否过于严格。
如果定义了健康检查,可以继续查看:
docker inspect --format '{{json .State.Health}}' <container_id>
docker stats --no-stream <container_id>
状态中如果出现 OOMKilled,应检查容器内存限制和进程实际占用;如果是非零 ExitCode,则沿应用异常方向检查。退出码为 0 只表示进程正常结束,对于本应长期运行的服务来说,退出仍然是问题。
“日志为空”不一定是 Docker 异常。容器根本没有创建时,自然没有容器日志;查错容器或服务名,也会拿到空结果。应用如果把日志写进文件而不是标准输出,docker logs 同样可能没有内容。进程在日志系统初始化前崩溃,也可能来不及留下任何输出。这时要结合退出码、入口命令、挂载目录和容器内的日志文件继续查。
域名已经解析,HTTP 还是打不开
先沿着 DNS、网络入口、反向代理和容器端口逐层走,不要直接把问题归因于域名解析。
dig +short A <domain>
dig +short AAAA <domain>
dig +short CNAME <domain>
curl -4 -vI http://<domain>
curl -6 -vI http://<domain>
CNAME 没有结果不一定异常,域名也可能直接提供 A 或 AAAA 记录。A 记录应指向当前服务器;如果还保留着失效的 AAAA 记录,部分客户端会优先尝试 IPv6,从而出现“浏览器打不开,但服务器 curl 正常”的现象,应删除或修正失效记录。
域名能正确解析,但连接超时,优先检查 80、443 是否被服务器防火墙或云安全组拦截。最好分别从服务器和外部网络执行 curl,避免本地网络、代理或回环路由掩盖真实链路。
域名请求已经到达反向代理后,要核对三件事:目标服务是否仍在运行,反向代理选择的上游地址和端口是否正确,上游协议是 HTTP 还是 HTTPS。容器里的应用如果只监听 127.0.0.1,其他容器和反向代理通常无法通过容器网络访问。反向代理应该指向容器网络中实际可达的服务端口,而不是只看宿主机上“映射出来的端口”。
502 通常表示代理与上游连接失败、连接被关闭或协议不匹配;504 更偏向等待上游响应超时。但应用自身也可能返回 502 或 404,所以不能只凭状态码下结论。应同时查看响应头、反向代理错误日志和应用容器日志。
如果启用了 Cloudflare 代理模式,需要额外比较代理结果与源站结果;DNS-only 模式则跳过这一步。可用 --resolve 保留域名和 SNI,直接访问源站:
curl -vI --resolve <domain>:80:<origin-ip> http://<domain>
curl -vI --resolve <domain>:443:<origin-ip> https://<domain>
如果源站只允许 Cloudflare 地址访问,直连源站失败并不能证明应用故障。部分只供 Cloudflare 使用的源站证书也不能被普通客户端直接信任。最终应结合当前 Cloudflare 设置、源站响应和代理日志判断。
HTTPS 报错,是证书没签下来还是应用本身有问题
把 DNS、证书签发、TLS 握手和 HTTP 响应分开测,避免把不同层的问题混成“SSL 坏了”。
curl -vI http://<domain>
curl -vI https://<domain>
openssl s_client -connect <domain>:443 -servername <domain> </dev/null
先确认 A、AAAA 记录指向当前服务器,并检查 80、443 是否可达。如果当前采用的证书验证方式需要通过 HTTP 完成验证,就要重点检查 80 端口是否开放,以及带正确 Host 的请求能否到达验证服务;如果采用 DNS 验证,则应检查 DNS 权限和验证记录是否成功更新。具体方式应按当前版本和对应官方文档确认。
HTTP 请求正常但 HTTPS 握手失败,优先检查证书是否过期、域名是否匹配、证书链是否完整,以及反向代理是否加载了最新证书。openssl s_client 可以帮助区分握手失败和证书内容问题。
如果 HTTPS 已经完成握手,但页面仍返回 404、502、504 或应用错误,说明问题已经越过 TLS 层,应回到反向代理上游、容器端口和应用日志排查。
不建议通过关闭证书校验来“修复”。跳过校验最多只能帮助确认错误发生在证书层,不能解决签发、域名匹配或证书链问题。具体证书开关和当前界面字段可能随版本变化,不应照搬旧教程中的菜单路径。
改完配置却没有生效,先对齐容器和日志时间
部署成功不代表新容器已经替换旧容器。要用容器 ID、镜像、创建时间和日志时间确认实际运行的是哪一次构建。
docker compose -f compose.yaml logs --since=10m <service>
docker inspect --format '{{.Created}} {{.Config.Image}} {{json .State}}' <container_id>
docker compose -f compose.yaml ps -a
如果只是执行了容器重启,而没有重新构建或重建镜像,构建参数、镜像标签、环境变量等配置可能根本没有应用。.env 的新值也通常要通过重新创建容器才能进入运行环境。
还要检查反向代理是否仍指向旧容器、是否选错 Compose 服务,或者宿主机上同时存在手工启动和 Coolify 启动的两套实例。容器名与 Compose 服务名不一定相同,应先用 docker compose ps -a 对照关系,不要凭名称猜。
排障时不要顺手执行下面的命令:
docker compose -f compose.yaml down -v
down -v 可能删除 Compose 项目声明的卷和匿名卷,清理未使用卷的命令也可能带走后续仍需要的数据。删除卷、清理镜像都应该是确认数据不再需要后的单独操作,而不是默认排障步骤。
另外,docker inspect、环境变量和日志都可能包含密码、令牌或连接串。公开报错前应统一脱敏,不要只删掉明显的 PASSWORD 字段。
下一次报错,先留下这几份证据
完整错误和时间线比“重新部署一次”更有助于定位问题。再次提交问题或搜索官方仓库 Issues 前,建议保存:
- 实际执行的完整命令,以及日志中的第一条原始报错。
- 报错时间、时区、服务器操作系统和 Docker、Compose 版本。
- 应用仓库的提交版本、镜像标签、Compose 文件路径。
- Coolify 部署日志和目标容器的运行日志。
- 容器 ID、容器状态、退出码和健康状态。
- 脱敏后的 DNS、
curl -vI和 TLS 检查结果。
date -Is
docker version
docker compose version
docker compose -f compose.yaml ps -a
然后用原始报错文本搜索 Coolify 官方仓库的 Issues,并附上上述环境信息。 不要只写“部署失败”“502”或“证书错误”,因为这些只是现象,不是足以定位故障的证据。












暂无评论内容