43

Recently, we had an outage due to Redis being unable to write to a file system (not sure why it's Amazon EFS) anyway I noted that there was no actual HEALTHCHECK set up for the Docker service to make sure it is running correctly, Redis is up so I can't simply use nc -z to check if the port is open.

Is there a command I can execute in the redis:6-alpine (or non-alpine) image that I can put in the healthcheck block of the docker-compose.yml file.

Note I am looking for command that is available internally in the image. Not an external healthcheck.

Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265

4 Answers4

40

If I remember correctly that image includes redis-cli so, maybe, something along these lines:

...
healthcheck:
   test: ["CMD", "redis-cli","ping"]
nitrin0
  • 760
  • 1
  • 5
  • 10
38

Although the ping operation from @nitrin0 answer generally works. It does not handle the case where the write operation will actually fail. So instead I perform a change that will just increment a value to a key I don't plan to use.

image: redis:6
healthcheck:
  test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265
27

I've just noticed that there is a phase in which redis is still starting up and loading data. In this phase, redis-cli ping shows the error

LOADING Redis is loading the dataset in memory

but stills returns the exit code 0, which would make redis already report has healthy.

Also redis-cli --raw incr ping returns 0 in this phase without actually incrementing this key successfully.

As a workaround, I'm checking whether the redis-cli ping actually prints a PONG, which it only does after the LOADING has been finished.

services:
  redis:
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      interval: 1s
      timeout: 3s
      retries: 5

This works because grep returns only 0 when the string ("PONG") is found.

fiedl
  • 5,667
  • 4
  • 44
  • 57
  • 2
    `[ "$(redis-cli ping)" = "PONG" ]` for exact match – TimTIM Wong Jul 27 '22 at 07:45
  • 1
    Adding to that, here is how it can look in the yaml: `test: "[ $$(redis-cli -a $REDIS_PASSWORD ping) = 'PONG' ]"` – Aivean Dec 12 '22 at 22:23
  • Or simply `test: redis-cli -a ${REDIS_PASSWORD} ping | grep PONG` using grep. Note, this is equivalent to `CMD-SHELL` per https://docs.docker.com/compose/compose-file/compose-file-v3/ – Aivean Dec 12 '22 at 22:26
  • Or if you're using Docker secrets: `test: ["CMD-SHELL", "redis-cli --no-auth-warning -a \"$$(cat $$REDIS_PASSWORD_FILE)\" ping | grep PONG"]` – jaredboone Dec 13 '22 at 00:41
  • Redis does not recommend use of `-a` and `-u` options for providing auth password. Here is what I came up with: `test: ["CMD-SHELL", "echo 'auth ${REDIS_PASSWORD}\nping' | redis-cli | grep PONG"]` – mrpandey Jul 24 '23 at 07:05
4

You can also add it inside the Dockerfile if your using a Redis image that contains the redis-cli:

Linux Docker

HEALTHCHECK CMD redis-cli ping || exit 1

Windows Docker

HEALTHCHECK CMD pwsh.exe -command \
try { \
    $response = ./redis-cli ping; \
    if ($response -eq 'PONG') { return 0} else {return 1}; \
} catch { return 1 }