Redis backs a startling share of the self-hosted world: Nextcloud's file locking, Paperless's task queue, n8n's job processing, Uptime Kuma's state, and every caching layer you've ever added. It's the least glamorous container on the server and the one whose failure takes down the most.
What it is
An in-memory key-value store. The name says cache but it's used as a queue, a session store, a rate limiter and a pub/sub bus. If your app has a "redis" dependency it's almost certainly for locks and queues rather than speed.
Before you start
- Redis has no authentication by default and trusts the network. Without
--requirepass, anything that can reach the port can read and rewrite everything. - Decide persistence.
--save ""makes it a pure cache that starts empty — correct if the app can rebuild. If it's a queue, you wantappendonly yes. - If you cap
maxmemory, you must also set an eviction policy.noevictionwith a full instance causes write errors that cascade into application failures.
1 — Create the directory
mkdir -p ~/services/redis/{data,conf}
cd ~/services/redis
openssl rand -base64 32
2 — Write the compose file
services:
redis:
image: redis:7-alpine
container_name: redis
restart: unless-stopped
ports:
- "127.0.0.1:6379:6379"
volumes:
- ./data:/data
- ./conf/redis.conf:/usr/local/etc/redis/redis.conf:ro
command: >
redis-server /usr/local/etc/redis/redis.conf
--requirepass CHANGE_ME
--appendonly yes
--appendfsync everysec
--maxmemory 256mb
--maxmemory-policy allkeys-lru
healthcheck:
test: ["CMD", "redis-cli", "-a", "CHANGE_ME", "--no-auth-warning", "ping"]
interval: 30s
timeout: 5s
retries: 3
stop_grace_period: 30s
# one-off inspector: run with --profile tools
redis-cli:
image: redis:7-alpine
profiles: ["tools"]
entrypoint: >
sh -c "redis-cli -a CHANGE_ME --no-auth-warning CONFIG GET *"
3 — Start it
docker compose up -d
docker exec -it redis redis-cli -a CHANGE_ME --no-auth-warning ping
docker exec -it redis redis-cli -a CHANGE_ME --no-auth-warning info memory | head -3
4 — First-run setup
- Confirm persistence is what you expect:
redis-cli -a CHANGE_ME CONFIG GET appendonlyshould showyes. - Check what the instance is actually used for:
redis-cli -a CHANGE_ME INFO keyspace. A cache and a queue have opposite requirements, and most installs end up needing both. - If you use
allkeys-lruand something is a queue, that eviction policy will eventually silently delete your pending jobs. Split into two Redis containers instead of hoping. - Set up a
maxmemoryalert before you set the cap. Out-of-memory in Redis looks like a mysterious application 500, not like a memory problem.
5 — Back it up
# online backup, no downtime
docker exec -it redis redis-cli -a CHANGE_ME --no-auth-warning BGSAVE
docker cp redis:/data/dump.rdb ./backups/dump-$(date +%F).rdb
# with appendonly, also copy the AOF directory
docker exec -it redis redis-cli -a CHANGE_ME --no-auth-warning info persistence | head -4
maxmemory-policy can evict Nextcloud's lock state, which shows up as random "file is locked" errors weeks later. Give each app its own.