Conteúdo

Redis com Docker: tutorial para configurar senha, persistência de dados e conexões

O Redis é um banco de dados de chave-valor que mantém os dados na memória, muito usado como cache, armazenamento de sessões, contador e fila. Executá-lo com Docker leva apenas alguns segundos.

Execução básica

$ docker run -d --name redis -p 127.0.0.1:6379:6379 redis:8-alpine
Unable to find image 'redis:8-alpine' locally
8-alpine: Pulling from library/redis
Digest: sha256:3811787313eba226a2ef38658c6ccb91cd5e110edc89c37767de373120a0e5a0
Status: Downloaded newer image for redis:8-alpine
6fbb2effcf1bc874eda1064575153984b6223fd6de15ac2452eae0bbf71a74f1

$ docker exec redis redis-cli PING
PONG

$ docker exec redis redis-cli SET greeting hello
OK

$ docker exec redis redis-cli GET greeting
hello

$ docker exec redis redis-cli SET session:abc "user42" EX 60
OK

$ docker exec redis redis-cli TTL session:abc
60

$ docker exec redis redis-server --version
Redis server v=8.10.2 sha=00000000:1 malloc=jemalloc-5.3.0 bits=64 build=6583f6419e33bdeb

$ docker rm -f redis
redis
  • -p 127.0.0.1:6379:6379: deixa a porta acessível apenas pela máquina local.
  • O contêiner já inclui o redis-cli, então você pode executar comandos diretamente.
  • SET ... EX 60 define a expiração automática em 60 segundos; TTL mostra os segundos restantes. Isso é comum em sessões e caches.

Para usar o modo interativo, execute docker exec -it redis redis-cli. O prompt 127.0.0.1:6379> será exibido. Digite um comando e pressione Enter; digite exit para sair.

Configurar uma senha

Por padrão, o Redis não tem senha. Se a porta estiver exposta, qualquer pessoa poderá ler e gravar dados e até invadir o host usando o Redis. Por isso:

  1. Se você não precisa se conectar de fora, não use -p; se precisar, vincule a porta somente a 127.0.0.1.
  2. Configure uma senha:
$ docker run -d --name redis redis:8-alpine redis-server --requirepass "change-me"
8dbd1f84d2541f264d93555142cb65f6497e9635111ff4f9544258516e06a0e2

$ docker exec redis redis-cli GET greeting
NOAUTH Authentication required.


$ docker exec redis redis-cli -a "change-me" PING
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
PONG

$ docker exec redis redis-cli -a "change-me" --no-auth-warning PING
PONG

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli PING
PONG

$ docker rm -f redis
redis
  • Sem senha, você recebe NOAUTH Authentication required..
  • Você pode passar a senha com -a, mas verá um aviso porque ela aparece na lista de processos. --no-auth-warning apenas oculta o aviso.
  • Uma opção melhor é passar a senha pela variável de ambiente REDISCLI_AUTH; o redis-cli a usa automaticamente e sem aviso.

String de conexão da aplicação (deixe o nome de usuário vazio):

redis://:change-me@redis:6379/0

O /0 no final é o número do banco de dados (0–15).

Persistência de dados

Os dados do Redis ficam na memória. Há duas formas de gravá-los em disco: snapshot RDB e log AOF. A imagem oficial habilita apenas o RDB por padrão, e os arquivos ficam em /data no contêiner, portanto você precisa montar um Volume.

Teste prático: o RDB não salva em tempo real

$ docker run -d --name redis -v redis_data:/data redis:8-alpine
882983e53f8e000fa65faaf8d71bbcbeb57192401b1854621172ce2df95c29a6

$ docker exec redis redis-cli SET visits 100
OK

$ docker rm -f redis
redis

$ docker run -d --name redis -v redis_data:/data redis:8-alpine
5ad1473152a6eafdfdb33df64f68355c73e454f10e6bc135688f7c51686bb059

$ docker exec redis redis-cli GET visits


$ docker exec redis redis-cli CONFIG GET save
save
3600 1 300 100 60 10000

Mesmo com o Volume montado, visits está vazio depois de recriar o contêiner com docker rm -f. CONFIG GET save mostra as condições de persistência padrão 3600 1 300 100 60 10000, que significam:

CondiçãoSignificado
3600 1Salvar se pelo menos 1 key mudar em 1 hora
300 100Salvar se pelo menos 100 keys mudarem em 5 minutos
60 10000Salvar se pelo menos 10000 keys mudarem em 1 minuto

Se apenas 1 key mudar, você precisa esperar 1 hora para que ela seja salva. docker rm -f encerra o Redis diretamente com SIGKILL, sem dar tempo para salvar.

Pare o contêiner normalmente com docker stop:

$ docker exec redis redis-cli SET visits 100
OK

$ docker stop redis
redis

$ docker logs redis 2>&1 | tail -n 5
1:M 13 Oct 2026 00:57:09.620 * User requested shutdown...
1:M 13 Oct 2026 00:57:09.620 * Saving the final RDB snapshot before exiting.
1:M 13 Oct 2026 00:57:09.621 * BGSAVE done, 1 keys saved, 0 keys skipped, 104 bytes written.
1:M 13 Oct 2026 00:57:09.623 * DB saved on disk
1:M 13 Oct 2026 00:57:09.623 # Redis is now ready to exit, bye bye...

$ docker start redis
redis

$ docker exec redis redis-cli GET visits
100

$ docker exec redis ls -l /data
total 4
-rw-------    1 redis    redis          104 Oct 13 00:57 dump.rdb

$ docker rm -f redis
redis

$ docker volume rm redis_data
redis_data

docker stop envia SIGTERM. Antes de encerrar, o Redis executa Saving the final RDB snapshot before exiting e salva os dados. Portanto:

  • Encerramentos normais (docker stop, docker compose down, desligamento normal do host) não causam perda de dados.
  • Falhas, queda de energia, docker rm -f ou encerramento pelo sistema por falta de memória causam a perda dos dados posteriores ao último snapshot.

AOF: registre cada gravação

Para uma persistência mais confiável, ative o AOF (Append Only File). Cada comando de gravação será registrado:

$ docker run -d --name redis -v redis_data:/data redis:8-alpine redis-server --appendonly yes
aaac5c67a222018db886e0f3a3306841ec4bba7e8ae0b4b4eca71dc5cede91c9

$ docker exec redis redis-cli SET visits 41
OK

$ docker exec redis redis-cli INCR visits
42

$ docker rm -f redis
redis

$ docker run -d --name redis -v redis_data:/data redis:8-alpine redis-server --appendonly yes
1c880b5c2e8ef54b65baaa1fd99b1b9c976eb42f2d9c52f1eb9188eaeda955e4

$ docker exec redis redis-cli GET visits
42

$ docker exec redis ls /data/appendonlydir
appendonly.aof.1.base.rdb
appendonly.aof.1.incr.aof
appendonly.aof.manifest

$ docker rm -f redis
redis

$ docker volume rm redis_data
redis_data

Mesmo após excluir à força com docker rm -f, visits continua sendo 42 depois que você recria o contêiner. /data/appendonlydir contém os arquivos AOF: base.rdb é o snapshot base, incr.aof registra cada gravação posterior e manifest lista os arquivos.

MétodoVantagensDesvantagens
RDB (padrão)Arquivo pequeno, carregamento rápido na reinicializaçãoEm caso de encerramento inesperado, os dados desde o último snapshot podem ser perdidos
AOFPor padrão, grava no disco uma vez por segundo; no máximo cerca de 1 segundo de dados pode ser perdidoArquivo maior e mais carga no disco quando há muitas gravações
Sem persistênciaMais rápidoTodos os dados desaparecem após a reinicialização; adequado apenas para cache puro

Para usar apenas como cache, você pode desativar totalmente a persistência: redis-server --save "" --appendonly no.

Use um arquivo de configuração e limite de memória

Quando houver muitos parâmetros, use um arquivo de configuração. redis-demo/redis.conf:

requirepass change-me
appendonly yes
maxmemory 64mb
maxmemory-policy allkeys-lru

Ao usar como cache, sempre configure maxmemory. Caso contrário, o Redis continuará consumindo memória até que a memória do host se esgote. Ao atingir o limite, o Redis age de acordo com maxmemory-policy:

PolíticaComportamento
noevictionValor padrão; rejeita novas gravações e retorna um erro
allkeys-lruRemove a chave menos usada recentemente entre todas as keys; mais comum para cache
volatile-lruRemove apenas keys com tempo de expiração definido
allkeys-lfuRemove as keys menos usadas

Teste: gravação de dados acima do limite

Use o redis-benchmark integrado ao Redis para gravar 300 mil entradas de 500 bytes cada (cerca de 150 MB), muito acima do limite de 64 MB:

$ docker run -d --name redis -v "$(pwd)/redis.conf:/usr/local/etc/redis/redis.conf:ro" -v redis_data:/data redis:8-alpine redis-server /usr/local/etc/redis/redis.conf
af187c21e0d6ecb0e9a0299200a6d866dc605d92c715e49df8a7abd850107040

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli CONFIG GET maxmemory*
maxmemory
67108864
maxmemory-clients
0
maxmemory-eviction-tenacity
10
maxmemory-samples
5
maxmemory-policy
allkeys-lru

$ docker exec redis redis-benchmark -a change-me -t set -n 300000 -r 300000 -d 500 -q
SET: 31043.05 requests per second, p50=0.903 msec

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli INFO memory | grep -E "^(used_memory_human|maxmemory_human|maxmemory_policy)"
used_memory_human:63.89M
maxmemory_human:64.00M
maxmemory_policy:allkeys-lru

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli INFO stats | grep evicted_keys
evicted_keys:95511

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli DBSIZE
115038

Comando equivalente no Windows (clique nas abas para alternar):

docker run -d --name redis -v "$(pwd)/redis.conf:/usr/local/etc/redis/redis.conf:ro" -v redis_data:/data redis:8-alpine redis-server /usr/local/etc/redis/redis.conf
docker run -d --name redis -v "${PWD}/redis.conf:/usr/local/etc/redis/redis.conf:ro" -v redis_data:/data redis:8-alpine redis-server /usr/local/etc/redis/redis.conf
docker run -d --name redis -v "%cd%/redis.conf:/usr/local/etc/redis/redis.conf:ro" -v redis_data:/data redis:8-alpine redis-server /usr/local/etc/redis/redis.conf
  • CONFIG GET maxmemory* confirma que o arquivo de configuração foi aplicado: 67108864 bytes equivalem a 64 MB, e a política é allkeys-lru.
  • Após a gravação, a memória ficou em 63.89M, sem ultrapassar o limite.
  • evicted_keys:95511: mais de 90 mil keys foram removidas automaticamente, restando cerca de 115 mil.

Agora, faça o mesmo com noeviction:

$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli CONFIG SET maxmemory-policy noeviction
OK

$ docker exec -e REDISCLI_AUTH=change-me redis sh -c 'head -c 2000000 /dev/zero | tr "\\0" x | redis-cli -x SET big-value'
OOM command not allowed when used memory > 'maxmemory'.


$ docker exec -e REDISCLI_AUTH=change-me redis redis-cli GET greeting

A memória está cheia. Ao gravar um valor de 2 MB, você recebe OOM command not allowed when used memory > 'maxmemory', e a aplicação apresenta um erro. Portanto, para cache puro, use allkeys-lru. Se o Redis armazenar dados que não podem ser perdidos (como uma fila), use noeviction e monitore o uso de memória.

Combine aplicações com Compose

Crie um contador Flask que incrementa visits no Redis a cada solicitação:

redis-demo/
├── compose.yaml
├── .env
└── app/
    ├── app.py
    ├── requirements.txt
    └── Dockerfile

app/app.py:

import os

import redis
from flask import Flask

app = Flask(__name__)
r = redis.Redis.from_url(os.environ["REDIS_URL"], decode_responses=True)


@app.get("/")
def index():
    visits = r.incr("visits")
    return {"message": "Hello from Flask + Redis", "visits": visits}

app/requirements.txt:

flask==3.1.*
gunicorn==23.*
redis==6.*

app/Dockerfile (consulte Aplicações Python para ver a explicação da sintaxe):

FROM python:3.14-slim
ENV PYTHONUNBUFFERED=1 PIP_NO_CACHE_DIR=1
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
USER nobody
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

.env:

REDIS_PASSWORD=change-this-password

compose.yaml:

services:
  app:
    build: ./app
    ports:
      - "8000:8000"
    environment:
      REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
    depends_on:
      redis:
        condition: service_healthy

  redis:
    image: redis:8-alpine
    command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}", "--appendonly", "yes"]
    environment:
      REDISCLI_AUTH: ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"]
      interval: 5s
      retries: 10
    restart: unless-stopped

volumes:
  redis_data:
ConfiguraçãoDescrição
@redis:6379 em REDIS_URLConecta usando o nome do serviço
${REDIS_PASSWORD} em commandO Compose substitui pelo valor real da senha a partir de .env
REDISCLI_AUTHFaz com que redis-cli dentro do contêiner (incluindo a verificação de integridade) informe a senha automaticamente
redis sem portsSomente o app precisa se conectar; o serviço não fica exposto externamente
$ docker compose up -d --build

[+] Building 0.3s (12/12) FINISHED
 => [internal] load local bake definitions                                                                                                       0.0s
 => => reading from stdin 486B                                                                                                                   0.0s
 => [internal] load build definition from Dockerfile                                                                                             0.0s
 => => transferring dockerfile: 263B                                                                                                             0.0s
 => [internal] load metadata for docker.io/library/python:3.14-slim                                                                              0.0s
 => [internal] load .dockerignore                                                                                                                0.0s
 => => transferring context: 2B                                                                                                                  0.0s
 => [1/5] FROM docker.io/library/python:3.14-slim@sha256:a2b82f3c48559aa0a8446d9af49826b6e2b2016f4cd2afabfe6013ec53729170                        0.0s
 => => resolve docker.io/library/python:3.14-slim@sha256:a2b82f3c48559aa0a8446d9af49826b6e2b2016f4cd2afabfe6013ec53729170                        0.0s
 => [internal] load build context                                                                                                                0.0s
 => => transferring context: 93B                                                                                                                 0.0s
 => CACHED [2/5] WORKDIR /app                                                                                                                    0.0s
 => CACHED [3/5] COPY requirements.txt .                                                                                                         0.0s
 => CACHED [4/5] RUN pip install -r requirements.txt                                                                                             0.0s
 => CACHED [5/5] COPY . .                                                                                                                        0.0s
 => exporting to image                                                                                                                           0.0s
 => => exporting layers                                                                                                                          0.0s
 => => exporting manifest sha256:2cb1f769137117a44dde49bfb2f8551a8ce989fe8bd0a72696ba37987c29fd13                                                0.0s
 => => exporting config sha256:88373d2af6030b965f8b4e878d871e906738cd9194ec77bd007c6bbbace7c1b9                                                  0.0s
 => => exporting attestation manifest sha256:c8f570c26323c3e08476544296d44ed0e159d27d9f25b86bf879cd08c6b6e186                                    0.0s
 => => exporting manifest list sha256:46bd2450b425a935481fb6ef8567c915f5543996f4e35018bdb955ecf858b361                                           0.0s
 => => naming to docker.io/library/redis-demo-app:latest                                                                                         0.0s
 => => unpacking to docker.io/library/redis-demo-app:latest                                                                                      0.0s
 => resolving provenance for metadata file                                                                                                       0.0s
[+] up 5/5
 ✔ Image redis-demo-app         Built                                                                                                             0.4s
 ✔ Network redis-demo_default   Created                                                                                                           0.0s
 ✔ Volume redis-demo_redis_data Created                                                                                                           0.0s
 ✔ Container redis-demo-redis-1 Healthy                                                                                                           5.8s
 ✔ Container redis-demo-app-1   Started                                                                                                           5.9s

$ curl -s http://localhost:8000/
{"message":"Hello from Flask + Redis","visits":1}

$ curl -s http://localhost:8000/
{"message":"Hello from Flask + Redis","visits":2}

$ curl -s http://localhost:8000/
{"message":"Hello from Flask + Redis","visits":3}

O app só inicia depois que o Redis fica Healthy; a cada solicitação, visits é incrementado em 1. Como o AOF está ativado e há um Volume montado, a contagem continua após recriar todos os contêineres:

$ docker compose up -d --force-recreate
[+] up 2/2
 ✔ Container redis-demo-redis-1 Healthy                                                                                                           6.1s
 ✔ Container redis-demo-app-1   Started                                                                                                           6.2s

$ curl -s http://localhost:8000/
{"message":"Hello from Flask + Redis","visits":4}

Por que usar grep PONG na verificação de integridade

Uma forma comum na internet é test: ["CMD", "redis-cli", "ping"]. Testamos o código de saída:

$ docker compose exec redis redis-cli ping; echo "exit code: $?"
PONG
exit code: 0

$ docker compose exec -e REDISCLI_AUTH=wrong redis redis-cli ping; echo "exit code: $?"
AUTH failed: WRONGPASS invalid username-password pair or user is disabled.
NOAUTH Authentication required.

exit code: 0

$ docker compose exec -e REDISCLI_AUTH=wrong redis sh -c "redis-cli ping | grep -q PONG"; echo "exit code: $?"
AUTH failed: WRONGPASS invalid username-password pair or user is disabled.
exit code: 1

Quando a senha está incorreta, redis-cli imprime NOAUTH Authentication required., mas o código de saída continua sendo 0. O Docker verifica o estado de saúde apenas pelo código de saída. Portanto, mesmo com a senha errada, a verificação passa e o app só falha ao se conectar depois de iniciar. Com | grep -q PONG, o código de saída só será 0 quando PONG for realmente recebido.

Comandos redis-cli mais usados

docker exec redis redis-cli INFO memory      # Uso de memória
docker exec redis redis-cli INFO stats       # Estatísticas, incluindo evicted_keys
docker exec redis redis-cli DBSIZE           # Quantidade de keys
docker exec redis redis-cli --scan --pattern 'session:*' | head
docker exec -it redis redis-cli MONITOR      # Exibe todos os comandos em tempo real (para depuração; afeta o desempenho; pressione Ctrl+C para encerrar)

Se uma senha estiver configurada, adicione -e REDISCLI_AUTH=senha ao docker exec.

Evite usar KEYS * em produção. Ele percorre todas as keys e bloqueia o Redis; quando há muitas keys, pode travar por vários segundos. Use SCAN (redis-cli --scan) no lugar.

Para navegar pelos dados em uma interface gráfica, você pode usar o Redis Insight oficial (imagem redis/redisinsight, porta padrão 5540). Na primeira abertura, você precisa ler e aceitar os termos da licença. Depois, adicione uma conexão e informe o nome do serviço Compose redis como host, a porta 6379 e a senha.

Sobre a licença do Redis e o Valkey

Em 2024, o Redis mudou sua licença para opções não open source, como RSALv2 / SSPL. A partir do Redis 8, também adicionou AGPLv3 como opção. Em 2024, a Linux Foundation lançou o Valkey, um fork compatível e open source (licença BSD), com comandos e uso quase idênticos:

$ docker run -d --name valkey valkey/valkey:8-alpine
Unable to find image 'valkey/valkey:8-alpine' locally
8-alpine: Pulling from valkey/valkey
Digest: sha256:081c2f5cb575efc901aa80ff9cdbd1ec6a301682fd35e1ebb4b0990a4a4a8507
Status: Downloaded newer image for valkey/valkey:8-alpine
3e7385b8f0d22a999ccf9306938e178c8f82bb4bc1ef9d304bd307917a890087

$ docker exec valkey valkey-cli PING
PONG

$ docker exec valkey redis-cli SET greeting hello
OK

$ docker exec valkey valkey-server --version
Valkey server v=8.1.10 sha=00000000:1 malloc=jemalloc-5.3.0 bits=64 build=fd3b186b1408478b

$ docker rm -f valkey
valkey

A imagem do Valkey inclui valkey-cli e o redis-cli compatível, e as bibliotecas Redis dos aplicativos também podem se conectar diretamente. O uso próprio comum do Redis não é afetado pela mudança de licença. Se você pretende oferecer o Redis como serviço para outras pessoas, verifique os termos da licença.

Resumo

  • O Redis não usa senha por padrão. Configure-a com --requirepass e passe-a com REDISCLI_AUTH.
  • O RDB não salva os dados em tempo real. Para maior confiabilidade, habilite --appendonly yes.
  • Ao usar como cache, configure maxmemory e allkeys-lru.
  • Escreva a verificação de integridade como redis-cli ping | grep -q PONG.

Exercícios

Exercício 1: Use docker exec redis redis-cli para definir uma key que expire após 30 segundos e consultar o tempo restante.

Resposta
docker exec redis redis-cli SET temp hello EX 30
docker exec redis redis-cli TTL temp

Se houver uma senha, adicione -e REDISCLI_AUTH=senha.

Perguntas frequentes

É obrigatório configurar uma senha no Redis?

Sim, se outras pessoas puderem se conectar. A melhor prática é não expor a porta e configurar uma senha.

Os dados desapareceram depois que o Redis reiniciou?

Por padrão, o RDB grava no disco apenas quando uma condição de persistência é atingida ou em um encerramento normal; docker rm -f ou uma falha fazem os dados se perderem. Ative o AOF quando precisar de persistência confiável.

Valkey e Redis são intercambiáveis?

Valkey é um fork de código aberto do Redis, compatível com seus comandos e protocolo. Em geral, não é preciso alterar a aplicação.

Atualizado 14 de outubro de 2026