ToolsOps

Docker Compose para Redis con contraseña

Un compose.yaml de Redis con contraseña (requirepass), persistencia AOF, healthcheck con redis-cli y puerto atado a localhost, más por qué un Redis sin AUTH y abierto se compromete en minutos.

Redis es rapidísimo y muy fácil de arrancar, y por eso es también muy fácil dejarlo mal configurado. Esta guía monta un Redis para desarrollo con dos cosas que mucha gente se salta: contraseña y persistencia. Sirve para usarlo como caché, cola o almacén de sesiones desde tu app local.

compose.yaml con AUTH y persistencia

services:
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}", "--appendonly", "yes"]
    environment:
      REDIS_PASSWORD: ${REDIS_PASSWORD}
    ports:
      - "127.0.0.1:6379:6379"
    volumes:
      - redis_data:/data
    healthcheck:
      test: ['CMD-SHELL', 'redis-cli -a "$$REDIS_PASSWORD" ping | grep -q PONG']
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s

volumes:
  redis_data:

El .env.example es de una sola línea. Cópialo a .env, pon una contraseña real y no subas el .env a git.

REDIS_PASSWORD=CHANGE_ME

Las decisiones que importan

  • --requirepass. Activa la autenticación. Sin esto, cualquiera que alcance el puerto manda en tu Redis.
  • command como lista. La forma exec deja que Compose sustituya ${REDIS_PASSWORD} desde el .env antes de arrancar, de modo que el servidor recibe la contraseña real. Una sola cadena sin shell dejaría la variable sin expandir.
  • --appendonly yes. Activa la persistencia AOF: cada escritura se registra en el volumen redis_data:/data, así no pierdes todo si reinicias.
  • 127.0.0.1:6379:6379. El puerto solo se publica en tu loopback. Otros contenedores del compose llegan a Redis por su nombre (redis:6379) sin necesidad de publicarlo.
  • healthcheck con redis-cli. Hace ping autenticado y comprueba que responde PONG. Usa $$REDIS_PASSWORD para que el $ lo evalúe el shell dentro del contenedor.

Comprobar que funciona

docker compose up -d
docker compose ps                       # debe aparecer healthy
docker compose exec redis \
  redis-cli -a "$REDIS_PASSWORD" ping    # -> PONG
docker compose exec redis \
  redis-cli -a "$REDIS_PASSWORD" set saludo hola
docker compose exec redis \
  redis-cli -a "$REDIS_PASSWORD" get saludo

El riesgo de un Redis abierto

El incidente clásico: alguien publica 6379:6379 (sin 127.0.0.1) en un servidor y deja Redis sin contraseña. En cuestión de minutos un bot lo encuentra, escribe claves y, en los casos peores, consigue ejecución de comandos o borra todo con FLUSHALL. Dos hábitos lo evitan: contraseña siempre, y no publicar el puerto salvo que de verdad necesites acceso desde el host (y entonces, atado a loopback).

Siguientes pasos

Ajusta este stack en el generador de Docker Compose y vuelve al índice de ejemplos para combinar Redis con tu app o tu base de datos.

Preguntas frecuentes

¿Por qué el command va como lista ["redis-server", ...] y no como texto?
Porque la forma de lista (exec) hace que Compose sustituya ${REDIS_PASSWORD} desde tu .env antes de arrancar el contenedor, así redis-server recibe la contraseña real. Si pones el command como una sola cadena, no pasa por una shell y la variable puede quedarse literal. La contraprestación es que docker compose config mostrará la contraseña ya sustituida: es asumible en local, pero por eso el secreto vive en el .env y no en el compose.
¿De verdad importa poner contraseña a Redis en local?
Importa en cuanto publicas el puerto. Redis sin requirepass acepta cualquier comando de quien llegue, incluido FLUSHALL o escribir claves para ejecución remota. Hay bots que escanean el 6379 abierto a Internet de forma constante. En local con el puerto atado a 127.0.0.1 el riesgo baja mucho, pero acostúmbrate a poner AUTH siempre: el día que ese compose acabe en un servidor con el puerto abierto, ya estará protegido.
¿Qué diferencia hay entre AOF y RDB?
Son las dos formas de persistir Redis. RDB hace snapshots periódicos del dataset (rápido, pero puedes perder lo último entre snapshots). AOF (--appendonly yes) registra cada escritura, así que pierdes menos datos ante un corte, a cambio de archivos mayores. Para desarrollo, AOF en el volumen /data es una opción sencilla y segura. Si usas Redis solo como caché de usar y tirar, puedes prescindir de persistencia.
Me sale (error) NOAUTH Authentication required, ¿qué hago?
Significa que Redis tiene contraseña pero tu cliente no la envía. Conéctate con redis-cli -a "$REDIS_PASSWORD" o, dentro del contenedor, docker compose exec redis redis-cli -a "$REDIS_PASSWORD". Si en su lugar ves (error) WRONGPASS, la contraseña no coincide: revisa que el .env y lo que pasa tu app sean el mismo valor y que no hayas dejado un volumen viejo con otra configuración.
¿Esto sirve para producción?
Es un punto de partida para desarrollo. En producción no publicarías el puerto al host, tratarías la contraseña como un secreto gestionado fuera de git, decidirías la política de persistencia y memoria (maxmemory, política de expulsión) según el uso, y valorarías réplicas o un Redis gestionado. La idea aquí es que aprendas el patrón correcto, no que despliegues esto tal cual de cara a usuarios.