为什么我的mongo容器的docker-compose健康检查总是失败?

tyky79it  于 2022-12-11  发布在  Docker
关注(0)|答案(7)|浏览(418)

我正在使用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

对于test,我也尝试过:

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

还有:

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

我也尝试过完全抛弃healthcheck,听从这个家伙的建议。一切都正常,但是在成功连接之前,我在输出中得到了可怕的错误:

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

mrwjdhj3

mrwjdhj31#

首先,我建议将docker-compose.yaml文件版本至少更新到3.4(version: "3.5"),然后请将start_period选项添加到mongo healthcheck
注意:只有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
zbq4xfa0

zbq4xfa02#

我们可以使用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
nhhxz33t

nhhxz33t3#

MongoDB 6.0中删除了mongo shell,替换为mongosh。
检查此方法是否适用于您:

mongo:
    image: mongo
    healthcheck:
      test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
xiozqbni

xiozqbni4#

我在这里找到了一个解决方案https://github.com/docker-library/healthcheck/tree/master/mongo
请注意,它解释了为什么运行状况检查未包含在官方映像www.example.com中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

在来自链接的示例中,它们使用hostvariable

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

它对我不起作用,因此我将host替换为localhost
停靠合成

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/
vsaztqbk

vsaztqbk5#

当我在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;"
2wnc66cl

2wnc66cl6#

这一条对我很有效:

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

sqxo8psd7#

注意,如果你使用的是mongodb的更新版本,你可能应该使用mongosh:

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

相关问题