编写服务文件

healthcheck:
  healthcheck:
    # image: curlimages/curl
    image: nicolaka/netshoot
    command: ["sh", "-c", "nc -zv my_service 8080"]
    interval: 30s
    timeout: 10s
    retries: 3
    start_period: 10s
  
# docker-compose.yml
version: '3'
services:
  my_service1:
    build: .
    ports:
      - "8080:8080"
    extends:
      file: ./healthcheck.yml
      service: my_service1
  my_service2:
    build: .
    ports:
      - "8081:8081"
    healthcheck:
      # 这是一个 Dockerfile 中 HEALTHCHECK 指令的配置,用于检测容器是否处于健康状态。在这种情况下,运行的命令是基于 shell 的命令,因此使用的是 CMD-SHELL 参数。CMD-SHELL 可以执行任何字符串作为 shell 命令。这个参数会在容器内部启动一个 shell,并将指定的命令传递给它来执行。在这种情况下,该命令使用 curl 命令检查本地主机上的端口8000是否可用,并将结果写入日志文件中。
      test: ["CMD-SHELL", "if curl -f http://localhost:8000; then echo \"$(date) - success\" >> /var/log/api-healthcheck.log; else echo \"$(date) - error\" >> /var/log/api-healthcheck.log; fi"]
      interval: 5s
      timeout: 10s
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
      # 将健康检查信息记录到独立的日志文件中
      driver_opts:
        path: "/var/log/api-activity.log"

这是一个 Docker Compose 文件中关于日志的配置。下面是每个字段的解释:

  • driver: 日志记录驱动程序,指定了容器的日志输出方式。在这种情况下,容器将使用 json-file 驱动程序来记录 JSON 格式的日志。
  • options: 日志记录选项,以键值对的形式提供日志记录驱动程序的特定设置。
  • max-size: 这个选项定义了单个日志文件的最大大小。在这种情况下,容器将允许每个日志文件达到 10MB 的大小。
  • max-file: 这个选项定义了要保留的日志文件的最大数量。在这种情况下,容器将保留3个旧日志文件,并删除任何更早的文件。
  • driver_opts: 指定了用于该驱动程序的其他选项。在这种情况下,我们为 json-file 驱动程序指定了一个独立的日志文件路径。
  • path: 这个选项指定了日志文件的存储路径,在这种情况下,容器的活动日志将被记录到 /var/log/api-activity.log 文件中。

总之,这个配置段指定了使用 Docker 内置的 json-file 日志记录驱动程序,将所有容器内部的活动日志记录到 /var/log/api-activity.log 文件中,并限制了单个日志文件的最大大小和要保留的日志文件的数量。

检查脚本

#!/bin/bash

# 从配置文件中读取日志文件路径列表
LOG_FILES=$(cat /etc/myapp-healthcheck.conf)

# 定义上次检查时间戳文件路径
LAST_ERROR_TIMESTAMP_FILE="/tmp/last_error_timestamp"

# 遍历每个日志文件,检查其中的错误信息并记录最后一条错误日志时间戳
for LOG_FILE in $LOG_FILES; do
    # 获取上次检查时的最后一条错误日志时间戳
    LAST_ERROR_TIMESTAMP=$(cat "$LAST_ERROR_TIMESTAMP_FILE.$(basename $LOG_FILE)" 2>/dev/null)

    # 查找新的错误日志并记录最后一条错误日志时间戳
    NEW_ERRORS=$(awk -v last="$LAST_ERROR_TIMESTAMP" '/error/{ if ($1" "$2 > last) print; }' "$LOG_FILE")
    if [ ! -z "$NEW_ERRORS" ]; then
        # 构造企业信使消息体
        MSG="{\"msgtype\": \"text\", \"text\": {\"content\": \"$NEW_ERRORS\"}}"

        # 发送企业信使消息
        curl -sS -H "Content-Type: application/json" -d "$MSG" "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_WEBHOOK_KEY"

        # 记录最后一条错误日志时间戳
        LAST_ERROR_TIMESTAMP=$(echo "$NEW_ERRORS" | awk '{ print $1" "$2; }' | tail -n 1)
        echo "$LAST_ERROR_TIMESTAMP" > "$LAST_ERROR_TIMESTAMP_FILE.$(basename $LOG_FILE)"
    fi
done

以下是一个示例 /etc/myapp-healthcheck.conf 文件的内容,其中包含了三个服务的日志文件路径:

/var/log/app1.log
/var/log/app2.log
/var/log/app3.log

请注意,在实际使用过程中,您需要将所有服务的日志文件路径添加到 /etc/myapp-healthcheck.conf 文件中,并且确保该文件的格式正确(例如,每个日志文件路径占用一行,没有多余的空格或注释)。然后,您可以将以下命令添加到 crontab 中,每隔5分钟运行一次:

*/5 * * * * /path/to/your/script.sh