Install Redis with Docker: Persistence, Basic Commands and Caching
What is Redis #
Redis is an in-memory data store. Because it keeps data in RAM, reads and writes take well under a millisecond, which makes it the usual choice for caches, sessions, rate limiters and queues. In this tutorial you run it in a container, secure it, persist its data and use it as a cache.
Run Redis #
docker run -d --name redis -p 6379:6379 -v redis-data:/data redis:7 redis-server --appendonly yes --requirepass "change-me"
-v redis-data:/datakeeps the data in a named volume (see Docker volumes).--appendonly yesturns on the append-only file, so Redis replays every write after a restart. Without it only periodic snapshots (RDB) are saved.--requirepasssets a password. Never publish a Redis without one to a network you do not control.
Connect with the client inside the container:
docker exec -it redis redis-cli -a change-me
Basic commands #
SET greeting "hello"
GET greeting
SET session:42 "alice" EX 60 # expires in 60 seconds
TTL session:42
INCR visits # atomic counter
HSET user:1 name "Ana" plan "pro" # hash
HGETALL user:1
LPUSH jobs "send-email" # list used as a queue
RPOP jobs
SADD tags "aws" "docker" # set
KEYS * # only for debugging, use SCAN in production
Use a prefix with a colon (user:1, session:42) to organize keys.
Redis in Docker Compose #
services:
redis:
image: redis:7
command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}"]
ports:
- "127.0.0.1:6379:6379"
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 3s
retries: 5
volumes:
redis-data:Binding to 127.0.0.1 exposes the port only on your machine. Other containers in the same Compose project reach Redis at redis:6379. See the Docker Compose tutorial.
Cache-aside pattern #
The application looks in Redis first and, on a miss, reads the database and stores the answer with an expiration.
import json, redis
r = redis.Redis(host="localhost", password="change-me", decode_responses=True)
def get_user(user_id, db):
key = f"user:{user_id}"
cached = r.get(key)
if cached:
return json.loads(cached)
user = db.query_user(user_id) # slow path
r.set(key, json.dumps(user), ex=300) # cache for 5 minutes
return user
The expiration keeps the cache from serving stale data forever.
Memory limits and eviction #
A cache must not grow without limit:
docker exec redis redis-cli -a change-me CONFIG SET maxmemory 256mb
docker exec redis redis-cli -a change-me CONFIG SET maxmemory-policy allkeys-lru
With allkeys-lru Redis evicts the least recently used keys when it reaches the limit. Check usage with INFO memory.
Redis on AWS #
For production on AWS use Amazon ElastiCache, which handles replication, failover and patching. Use the container for development and tests.