Docker Compose 显示 Up,为什么网站还没准备好

本文由 AI 辅助整理,并依据官方文档核对。配置是通用示例,未在实际项目中运行;服务名、端口、接口和时间参数需要按项目调整。

本文首发于知乎,此处为同文同步。

发布一个网站时,终端里的容器都显示 Up,浏览器却仍然报错,并不矛盾。容器进程正在运行、应用可以接收请求、用户能完成业务,是三个需要分别验证的结果。上线记录只写"容器已启动",会把后两项留空。

一、先约定"准备好"意味着什么

以一个带数据库的预约网站为例。首页可能只是静态页面,返回 200 时数据库连接池仍未建立;登录页可以打开,也不代表预约查询成功。

可以为应用设计一个只读、轻量的 /ready 接口:初始化完成且关键依赖满足约定时返回 200,否则返回 503。明确它检查什么,例如当前应用凭据能否完成必要查询;也明确它不检查什么,例如短信供应商是否可用。不要在每次探测中创建订单、发短信或执行耗时全表查询。响应只需给出简短状态,不返回连接密码或内部配置。

这里的 200/503 是示例接口约定,Docker 不会替应用实现接口,也不会理解"预约成功"。

二、把启动顺序与健康条件一起写清楚

Compose 的简写 depends_on 只保证依赖先启动,不等待它健康。长写法的 service_healthy 才会等待依赖通过已配置的 healthcheck,再启动依赖它的服务。这是启动阶段的约束。运行中依赖断开后的重连、降级和告警仍需单独设计。Docker 启动顺序说明

假设现有项目已有 app 和 proxy 两个服务,可以合并以下片段。它省略了镜像、网络及代理配置,不是完整的部署文件;示例要求 app 镜像已有 /bin/sh、curl,并实现上述 /ready 接口。

yaml 复制代码
services:
  app:
    healthcheck:
      test:
        - CMD-SHELL
        - >-
          code=$$(curl -q --noproxy '*' -sS --max-time 3
          -o /dev/null -w '%{http_code}'
          http://127.0.0.1:8080/ready)
          && [ "$$code" = 200 ]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 30s
  proxy:
    depends_on:
      app:
        condition: service_healthy

这次请求限制为 3 秒,保留错误信息,并要求传输成功且状态码恰好为 200;重定向到登录页也不会通过。首个参数 -q 忽略 curl 默认配置,--noproxy '*' 让这个本机探测不走代理。单看 curl 的默认退出成功并不能排除 HTTP 错误,因此示例另外比较状态码。curl 手册

代码里的 $$ 用来避免 Compose 提前展开变量,交给容器内 shell 处理。不能直接把这段带 $$ 的文本原样粘进普通 shell 执行。Compose 插值说明

start_period 是初始化宽限期,并不表示暂停探测 30 秒;期间失败通常不计入重试次数,但一旦探测成功,后续连续失败就会开始计数。参数要根据实际启动耗时调整,不能用很长的宽限期掩盖持续错误。Docker 健康检查说明

三、容器内通过之后,还差哪一项

在常见的独立容器网络中,127.0.0.1 指向执行探测的 app 容器。它没有经过反向代理、域名解析或公网 TLS。另一个容器访问 app 时应使用共同网络内的服务名和容器端口;宿主机访问映射端口是另一条路径。Compose 网络说明

healthy 只反映已配置探测的结果,不保证之后始终可用。本片段不会仅因 unhealthy 自动重启容器;Docker 容器重启策略处理的是退出、停止等条件,不能把健康状态变化当成进程退出。这里也没有定义运行中摘除故障实例的规则,是否停止转发请求,应由代理配置或发布流程另外明确。Docker 容器重启策略

因此,验收至少留下三条有时间戳的结果:

  • 容器状态:进程是否运行,健康检查是否通过。
  • 应用就绪:/ready 的实际返回,以及它覆盖的依赖。
  • 用户入口:从预期访问位置打开正式域名,并完成一个约定的只读业务步骤。

若进程运行而 /ready 失败,就检查应用初始化和接口覆盖的依赖;容器内就绪而用户入口失败,就检查代理与访问路径。不要为了让状态变绿,把探测改成永远返回成功。健康检查的价值,来自失败时能指出尚未满足的条件。

相关推荐
a5986522 小时前
ARM服务器部署Docker云手机,多开实例性能实测
服务器·arm开发·docker·云手机
7177773 小时前
国内 Docker 镜像仓库推荐:Gitee 与主流方案对比及选型指南
docker·容器·gitee
江湖有缘3 小时前
Docker实战 | Docker部署Minimalist-web-notepad个人笔记本
前端·docker·notepad++
weixin_437961924 小时前
Docker安装(windows)
windows·docker·容器
GPU实战笔记4 小时前
Docker Hub 项目镜像拉取前提:缓存区域节点的可扩容数据盘
docker·docker hub·容器镜像·a100·gpu云计算
承渊政道4 小时前
极空间部署Portainer实战:Docker Socket、9000端口、容器管理与固定地址访问
运维·docker·容器·内网穿透·cpolar·portainer
禁默5 小时前
玩客云部署EasyVoice实战:HiNas、Docker、ARMv7、9001与固定地址访问(1)
docker·容器·语音识别·cpolar
北风toto5 小时前
Linux 服务器通过 tgz 离线部署 Docker
linux·服务器·docker
羑悻的小杀马特5 小时前
超越Bridge:全面掌握Docker网络隔离与通信的底层逻辑!
运维·网络·docker·容器