Mongodb 为什么docker编写的mongo容器健康检查总是失败?

Mongodb 为什么docker编写的mongo容器健康检查总是失败?,mongodb,docker,docker-compose,Mongodb,Docker,Docker Compose,我正在使用docker compose建立一个Express/React/Mongo应用程序。目前,我可以在express应用程序中使用重试逻辑支持所有内容。然而,我更愿意使用Docker的方法来防止容器开始旋转时出现一连串的错误。但是,当我在我的docker compose.yml中添加healthcheck时,它会在间隔/重试时间限制内挂起,并以以下方式退出: ERROR: for collector Container "70e7aae49c64" is unhealthy. ERRO

我正在使用
docker compose
建立一个Express/React/Mongo应用程序。目前,我可以在express应用程序中使用重试逻辑支持所有内容。然而,我更愿意使用Docker的方法来防止容器开始旋转时出现一连串的错误。但是,当我在我的
docker compose.yml
中添加
healthcheck
时,它会在间隔/重试时间限制内挂起,并以以下方式退出:

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
对于
测试
,我还尝试了:

["CMD", "nc", "-z", "localhost", "27017"] 
以及:

我也试着完全抛弃了健康检查,听从了医生的建议。一切正常,但在成功连接之前,输出中出现了可怕的错误:

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
时获得干净的启动输出。我也研究了中的一些解决方案,但我也没有太多的运气使用
等待它。在启动其他容器并实现干净的启动之前,等待Mongo启动并运行的正确方法是什么?

首先,我建议将docker-compose.yaml文件版本至少更新为3.4(
版本:“3.5”
),然后请将
启动周期
选项添加到Mongo
healthcheck

注意:只有v3.4及更高版本的撰写文件格式才支持开始时间

开始阶段为需要时间引导的容器提供初始化时间。在此期间发生的探头故障不会计入最大重试次数。但是,如果运行状况检查在启动期间成功,则认为容器已启动,所有连续失败都将计入最大重试次数

所以它看起来像这样:

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

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

    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;"

我在这里找到了解决办法

注意,它解释了为什么健康检查不包括在官方形象中

docker healthcheck

#!/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替换了host

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的命令进行运行状况检查,正如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

我想要一个更新的版本,但是。这会有所不同吗?现在进行更改,我将向您发布:)+1以了解新内容,但这仍然会导致启动时出现来自Express应用程序中重试逻辑的
MongoDB连接错误。不过,谢谢你的调查,如果你还有其他想法,我愿意接受!Try:
取决于:[“mongo”]
$ 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