繁体   English   中英

为什么我的mongo容器的docker-compose healthcheck总是失败?

[英]Why does the docker-compose healthcheck of my mongo container always fail?

我正在使用docker-compose建立一个 Express/React/Mongo 应用程序。 我目前可以在 express 应用程序中使用重试逻辑来解决所有问题。 但是,我更愿意使用Docker的健康检查来防止容器最初启动时出现错误串。 但是,当我在我的healthcheck中添加健康docker-compose.yml时,它会在间隔/重试时间限制内挂起并退出:

ERROR: for collector  Container "70e7aae49c64" is unhealthy.

ERROR: for server  Container "70e7aae49c64" is unhealthy.
ERROR: Encountered errors while bringing up the project.

似乎我的健康检查从未返回健康状态,我不完全确定为什么。 我的全部docker-compose.yml

version: "2.1"
services:
  mongo:
    image: mongo
    volumes:
      - ./data/mongodb/db:/data/db
    ports:
      - "${DB_PORT}:${DB_PORT}"
    healthcheck:
      test: echo 'db.runCommand("ping").ok' | mongo mongo:27017/test --quiet 1
      interval: 10s
      timeout: 10s
      retries: 5
  collector:
    build: ./collector/
    environment:
      - DB_HOST=${DB_HOST}
      - DB_PORT=${DB_PORT}
      - DB_NAME=${DB_NAME}
    volumes:
      - ./collector/:/app
    depends_on:
      mongo:
        condition: service_healthy
  server:
    build: .
    environment:
      - SERVER_PORT=$SERVER_PORT
    volumes:
      - ./server/:/app
    ports:
      - "${SERVER_PORT}:${SERVER_PORT}"
    depends_on:
      mongo:
        condition: service_healthy

对于test ,我也尝试过:

["CMD", "nc", "-z", "localhost", "27017"] 

和:

["CMD", "bash", "/mongo-healthcheck"]

我也healthcheck完全放弃健康检查,听从这个人的建议。 一切正常,但在成功连接之前,我在 output 中遇到了可怕的错误:

collector_1  | MongoDB connection error: MongoNetworkError: failed to connect to server [mongo:27017] on first connect [MongoNetworkError: connect 
ECONNREFUSED 172.21.0.2:27017]
collector_1  | MongoDB connection with retry
collector_1  | MongoDB connection error: MongoNetworkError: failed to connect to server [mongo:27017] on first connect

最终目标是在运行docker-compose up --build时干净启动 output。 我也研究了这个问题中的一些解决方案,但我也没有太多运气wait-for-it 在启动其他容器并实现干净启动之前等待 Mongo 启动并运行的正确方法是什么?

首先,我建议将 docker-compose.yaml 文件版本更新为至少 3.4( version: "3.5" ),然后请将start_period选项添加到您的 mongo healthcheck

注意:start_period 仅支持 v3.4 及更高版本的撰写文件格式。

start period 为需要时间引导的容器提供初始化时间。 在此期间的探测失败将不计入最大重试次数。 但是,如果在启动期间健康检查成功,则认为容器已启动,所有连续失败都将计入最大重试次数。

所以它看起来像这样:

healthcheck:
  test: echo 'db.runCommand("ping").ok' | mongo mongo:27017/test --quiet
  interval: 10s
  timeout: 10s
  retries: 5
  start_period: 40s

我们可以使用 MongoDB 的serverStatus命令来进行健康检查,就像 MongoDB 文档这样说的:

监控应用程序可以定期运行此命令来收集有关实例的统计信息。

由于此命令serverStatus需要身份验证,因此您需要设置类似于以下配置的健康检查:

version: '3.4'

services:
  mongo:
    image: mongo
    restart: always
    healthcheck:
      test: echo 'db.runCommand({serverStatus:1}).ok' | mongo admin -u $MONGO_INITDB_ROOT_USERNAME -p $MONGO_INITDB_ROOT_PASSWORD --quiet | grep 1
      interval: 10s
      timeout: 10s
      retries: 3
      start_period: 20s
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example

就是这样。 如果您的 MongoDB 实例运行状况良好,您将看到与我类似的内容:

$ docker ps
CONTAINER ID  IMAGE  COMMAND                 CREATED         STATUS                   PORTS      NAMES
01ed0e02aa70  mongo  "docker-entrypoint.s…"  11 minutes ago  Up 11 minutes (healthy)  27017/tcp  demo_mongo_1

我在这里找到了一个解决方案https://github.com/docker-library/healthcheck/tree/master/mongo

注意,它解释了为什么健康检查没有包含在官方镜像中https://github.com/docker-library/cassandra/pull/76#issuecomment-246054271

码头工人健康检查

#!/bin/bash
set -eo pipefail

if mongo --quiet "localhost/test" --eval 'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)'; then
    exit 0
fi

exit 1

在链接的示例中,它们使用宿主变量

host="$(hostname --ip-address || echo '127.0.0.1')"

if mongo --quiet "$host/test" --eval 'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)'; then
# continues the same code

它对我不起作用,所以我用localhost替换了主机

docker-compose 中

mongo:
  build:
    context: "./mongodb"
    dockerfile: Dockerfile
  container_name: crm-mongo
  restart: always
  healthcheck:
    test:  ["CMD", "docker-healthcheck"]
    interval: 10s
    timeout: 2s
    retries: 10

或者,您可以在容器中执行健康检查。 更改Dockerfile或那个。

FROM mongo:4

ADD docker-healthcheck /usr/local/bin/

请注意,如果您使用 mongodb 的较新版本,您可能应该使用 mongosh:

    healthcheck:
      test: ["CMD","mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 5s
      timeout: 5s
      retries: 3
      start_period: 5s

当我执行echo db.runCommand("ping").ok' | mongo localhost:27017/test --quiet 1 echo db.runCommand("ping").ok' | mongo localhost:27017/test --quiet 1命令在docker容器中,结果为:

    2019-04-19T02:39:19.770+0000 E -        [main] file [1] doesn't exist
    failed to load: 1

尝试这个

healthcheck:
  test: bash -c "if mongo --eval 'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)'; then exit 0; fi; exit 1;"

这个对我有用:

healthcheck:
  test: ["CMD","mongo", "--eval", "db.adminCommand('ping')"]
  interval: 10s
  timeout: 10s
  retries: 5

从 MongoDB 6.0 中删除了 mongo shell。 替代品是mongosh。

尝试这个。 echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet

mongo:图像:mongo 健康检查:测试:echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM