Docker Compose 健康检查实战:让服务在华为云上自愈

举报
yd_235670046 发表于 2026/10/22 21:24:11 2026/10/22
【摘要】 容器显示 Up 不等于服务可用。本文从 healthcheck 的写法讲起,说明 depends_on: service_healthy 的正确用法,并在华为云 Flexus 上完整演示部署、安全组放行与 unhealthy 排错的全过程。

很多人第一次把应用搬到云服务器上,都会碰到同一个迷惑:容器明明是 Up 的,端口也通,但请求就是 502 / 504。

翻遍日志可能只找到一句 connection refused。原因在于,Docker 判断"容器还活着"的标准只有一个——主进程有没有退出。进程没死,容器就一直显示 running,哪怕里面的应用早就崩了。

想让服务真正具备"自愈"能力,第一步是把健康状态显式描述出来,也就是 healthcheck。

一、healthcheck 到底在检查什么

healthcheck 的本质很简单:在容器内部定时跑一条命令,退出码为 0 就算健康。

最典型的用法是请求自己的健康检查接口:

FROM python:3.11-slim
WORKDIR /app
COPY . .

RUN pip install --no-cache-dir fastapi uvicorn

# 每 30 秒探一次,单次最多等 3 秒,连着失败 3 次才判定为 unhealthy
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
    CMD curl -fsS http://localhost:8000/health || exit 1

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

这里有个容易忽略的细节:curl 不一定存在。精简镜像里更稳妥的做法是直接用 Python 自己探:

HEALTHCHECK CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://localhost:8000/health').status==200 else 1)"

如果服务是用 compose 编排的,就可以不改动镜像,直接写在 docker-compose.yml 里:

services:
  api:
    image: my-api:1.0
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8000/health"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 40s
    restart: unless-stopped

start_period 特别值得强调。应用刚启动时可能要二十多秒才能连上数据库,这段时间里如果探针一直失败,容器会被过早判定为 unhealthy,触发重启——于是陷入"启动 → 检查失败 → 重启 → 再失败"的死循环。给它留一段"宽限期",是新手最容易踩的坑。

二、让依赖服务"等"健康,而不是"等"启动

很多人在 compose 里这么写:

  worker:
    depends_on:
      db:            # 老写法

或者新写法:

  worker:
    depends_on:
      db:
        condition: service_started

这两种都只保证"db 容器启动了",并不保证"db 能连上了"。worker 很可能在数据库还没 ready 的时候就去建立连接,然后报错退出。

稳妥的写法是等健康状态:

  worker:
    depends_on:
      db:
        condition: service_healthy

这样 worker 会一直等到 db 的 healthcheck 通过(healthy)才真正启动。nginx 这类反向代理也可以用同样的方式依赖后端。

三、在华为云 Flexus 上落地的完整流程

以一台轻量应用服务器为例(Flexus 应用服务器 L 实例,系统选 Ubuntu 22.04):

1. 安装 Docker

curl -fsSL https://get.docker.com | sh
sudo systemctl enable --now docker
sudo docker compose version

2. 准备项目目录

mkdir -p ~/hello && cd ~/hello

目录保持简单:

hello/
├── docker-compose.yml
└── api/
    ├── Dockerfile
    └── main.py

main.py 里加一个最小可用的健康接口:

from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
def health():
    return {"status": "ok"}

@app.get("/")
def index():
    return {"hello": "huaweicloud"}

3. 写编排文件

services:
  api:
    build: ./api
    ports:
      - "8000:8000"
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
      interval: 15s
      timeout: 3s
      retries: 5
      start_period: 30s
    restart: unless-stopped

4. 放行安全组

容器里监听了 8000,并不代表外面就能访问。需要到控制台的安全组里添加入方向规则放行 TCP 8000。正式环境更推荐的做法是只放行 80 / 443,前面挂一层 Nginx,再由 Nginx 反代到 8000,这样业务端口根本不必暴露。

5. 启动并验证

cd ~/hello
sudo docker compose up -d --build

# 看健康状态
sudo docker compose ps
# NAME            SERVICE    STATUS                 PORTS
# hello-api-1     api        Up 2 minutes (healthy)  0.0.0.0:8000->8000/tcp

再从外部验证一次:

curl -s http://<你的公网IP>:8000/health
# {"status":"ok"}

四、排错三板斧

一旦出现 unhealthy,按这个顺序查,基本都能定位问题。

看状态

sudo docker compose ps

输出里出现 Up 5 minutes (unhealthy),就说明 Docker 已经在替你盯着这个容器了。

看健康检查历史(能看到最近几次探测的退出码和错误输出)

sudo docker inspect --format '{{json .State.Health}}' hello-api-1 | python3 -m json.tool

看应用日志

sudo docker compose logs --tail=100 -f api

常见原因无非三类:应用自身启动失败、端口配置写错、探针命令在容器里根本不存在(alpine 这类精简镜像里没有 curl,改用 wget 或 nc 即可)。

五、一点延伸

healthcheck 解决的是"状态可见",而"自动恢复"是另一件事:

  • restart: unless-stopped 负责进程崩了之后自动拉起;
  • healthcheck 负责让编排系统知道它到底好不好;
  • 两者配合,才能在 depends_on: condition: service_healthy 这种编排里形成可靠的启动顺序。

顺手再给容器加上资源限制,避免某个进程把整机吃满:

    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M

小结

把"容器在跑"和"服务可用"区分开,是用 Docker 上云之后最值得养成的习惯。一个 healthcheck 加上 depends_on: service_healthy,成本只有几行 YAML,却能把绝大部分"偶发启动失败"和"莫名其妙的 502"提前暴露在编排层,而不是等到用户投诉才发现。

文中给出的目录结构、compose 配置与排查命令,可直接按步骤在华为云 Flexus 上复现验证;如果你的服务有数据库依赖,建议优先把 start_period 和 condition: service_healthy 这两处配齐,收益最明显。

本文为原创文章,配置示例基于华为云 Flexus(Ubuntu 22.04)与 Docker Compose 官方文档整理。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。