Docker / Healthcheck

Healthcheck

Container ажиллаж байна гэдэг нь аппликейшн зөв ажиллаж байна гэсэн үг биш. Процесс ажиллаж байж болох ч хүсэлтэд хариу өгөхгүй байж болно. HEALTHCHECK нь аппликейшн үнэхээр эрүүл эсэхийг автоматаар шалгадаг.

HEALTHCHECK instruction

dockerfile
HEALTHCHECK [OPTIONS] CMD <команд>
dockerfile
FROM node:20-alpine

WORKDIR /app
COPY . .
RUN npm ci

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD wget -qO- http://localhost:3000/health || exit 1

CMD ["node", "index.js"]

Тохируулгын утгууд

| Сонголт | Анхдагч | Тайлбар | | ---------------- | ------- | ---------------------------------------------------------------- | | --interval | 30s | Хэр давтамжтай шалгах | | --timeout | 30s | Шалгалт хэр удаан хүлээх | | --start-period | 0s | Эхлэлийн хугацаа — энэ үед амжилтгүй болсон шалгалт тоологдохгүй | | --retries | 3 | Хэдэн удаа амжилтгүй болвол unhealthy гэх |

start-period яагаад чухал вэ?

Апп эхлэхэд цаг хэрэгтэй (database connection, cache warm-up). --start-period тохируулаагүй бол эхлэх үед unhealthy болж, дахин restart хийгдэнэ:

dockerfile
# ✅ Апп 15 секундэд бэлэн болдог бол
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
  CMD wget -qO- http://localhost:3000/health || exit 1

Healthcheck команд сонгох

wget (Alpine-д байдаг)

dockerfile
HEALTHCHECK CMD wget -qO- http://localhost:3000/health || exit 1

-q — чимээгүй горим
-O- — stdout руу гаргах

curl

dockerfile
HEALTHCHECK CMD curl -f http://localhost:3000/health || exit 1

-f — HTTP алдааны код бол exit 1 буцаана
Curl Alpine image-д анхдагч байдлаар байхгүй — суулгах шаардлагатай.

Node.js скрипт

dockerfile
HEALTHCHECK CMD node -e "require('http').get('http://localhost:3000/health', r => process.exit(r.statusCode === 200 ? 0 : 1))"

Зөвхөн процесс шалгах

HTTP endpoint байхгүй тохиолдолд:

dockerfile
HEALTHCHECK CMD pgrep -f "python main.py" || exit 1

/health endpoint бэлдэх

Апп-д зориулагдсан health endpoint байх нь зүйтэй:

javascript
// Express
app.get("/health", (_req, res) => {
  res.status(200).json({ status: "ok", uptime: process.uptime() });
});
python
# FastAPI
@app.get("/health")
def health():
    return {"status": "ok"}

Гүнзгийрүүлсэн шалгалт — database холболт ч шалгана:

javascript
app.get("/health", async (_req, res) => {
  try {
    await db.query("SELECT 1");
    res.status(200).json({ status: "ok", db: "connected" });
  } catch {
    res.status(503).json({ status: "error", db: "disconnected" });
  }
});

Healthcheck төлөв шалгах

bash
# Container-ийн health төлөв харах
docker ps
# STATUS
# Up 2 minutes (healthy)
# Up 30 seconds (health: starting)
# Up 5 minutes (unhealthy)

# Дэлгэрэнгүй мэдээлэл
docker inspect --format='{{json .State.Health}}' mycontainer

JSON гаралт:

json
{
  "Status": "healthy",
  "FailingStreak": 0,
  "Log": [
    {
      "Start": "2024-01-15T10:00:00Z",
      "End": "2024-01-15T10:00:00.1Z",
      "ExitCode": 0,
      "Output": "{\"status\":\"ok\"}"
    }
  ]
}

docker run-д healthcheck нэмэх

Dockerfile-д байхгүй ч docker run үед нэмж болно:

bash
docker run -d \
  --health-cmd "wget -qO- http://localhost:3000/health || exit 1" \
  --health-interval 30s \
  --health-timeout 5s \
  --health-start-period 10s \
  --health-retries 3 \
  --name myapp \
  myimage

Healthcheck унтраах:

bash
docker run --no-healthcheck myimage

Docker Compose-д healthcheck

yaml
services:
  app:
    build: .
    ports:
      - "3000:3000"
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      start_period: 15s
      retries: 3

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

CMD — exec форм, shell дамжуулахгүй
CMD-SHELL/bin/sh -c дамжуулна, pipe болон || ашиглаж болно

depends_on + condition

Healthcheck-тэй сервисийг depends_on-д ашиглах:

yaml
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  app:
    build: .
    depends_on:
      db:
        condition: service_healthy # db healthy болтол хүлээнэ
    environment:
      DATABASE_URL: postgresql://postgres:secret@db:5432/postgres

condition утгууд:

  • service_started — container зүгээр эхэлсэн бол (анхдагч)
  • service_healthy — healthcheck амжилттай болсон бол
  • service_completed_successfully — container 0-тэй зогссон бол

Дараагийн хичээлд:

CPU ба санах ойн хязгаарлалт — container хэт их нөөц ашиглахаас хамгаалах.