用 Compose 部署一个生产基线的 Redis:强制密码、AOF(每秒刷盘)加 RDB 双持久化、maxmemory + LRU 淘汰、危险命令改名、端口只绑回环、配置和数据全部持久化到宿主机。
示例锁定 redis:7.4-alpine(当前稳定版);文末附 Redis 6 的差异。
一、目录结构
/opt/redis/
├── docker-compose.yml
├── .env # 600,放 Redis 密码
└── redis/
├── conf/redis.conf
├── data/ # chown 999:999(AOF + RDB)
└── logs/ # chown 999:999
sudo mkdir -p /opt/redis/redis/{conf,data,logs}
sudo chown -R 999:999 /opt/redis/redis/{data,logs}
Redis 官方镜像内运行用户 uid 为 999。
二、.env
umask 077
cat > /opt/redis/.env <<'EOF'
REDIS_PASSWORD=替换为强密码
TZ=Asia/Shanghai
EOF
chmod 600 /opt/redis/.env
密码用 openssl rand -base64 24 生成;不要在密码里放 #、空格等容易被配置解析截断的字符,或使用纯 hex(openssl rand -hex 24)。
三、docker-compose.yml
name: redis-stack
x-logging: &default-logging
driver: json-file
options:
max-size: "20m"
max-file: "3"
services:
redis:
image: redis:7.4-alpine
container_name: redis7
restart: unless-stopped
logging: *default-logging
env_file:
- .env
# 密码通过启动参数注入,不写进配置文件
command:
- sh
- -c
- 'exec redis-server /etc/redis/redis.conf --requirepass "$$REDIS_PASSWORD"'
ports:
- "127.0.0.1:6379:6379"
volumes:
- ./redis/data:/data
- ./redis/conf/redis.conf:/etc/redis/redis.conf:ro
- ./redis/logs:/var/log/redis
security_opt:
- no-new-privileges:true
mem_limit: 1g
mem_reservation: 256m
healthcheck:
test: ["CMD-SHELL", "redis-cli -a \"$$REDIS_PASSWORD\" --no-auth-warning ping | grep -q PONG"]
interval: 10s
timeout: 5s
retries: 6
四、redis.conf
redis/conf/redis.conf:
# ---------- 网络 ----------
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 300
tcp-keepalive 60
# ---------- 内存(容器限额 1g,预留一半给碎片/缓冲)----------
maxmemory 512mb
maxmemory-policy allkeys-lru
# ---------- AOF:主持久化,每秒刷盘 ----------
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# ---------- RDB:兜底快照 ----------
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir /data
# ---------- 日志 ----------
loglevel notice
logfile /var/log/redis/redis.log
# ---------- 慢查询(10ms)----------
slowlog-log-slower-than 10000
slowlog-max-len 128
# ---------- 加固 ----------
# requirepass 通过容器启动参数注入,不写入本文件
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command KEYS ""
rename-command CONFIG "CONFIG_a9f3" # 需要保留时改成难猜的别名;不需要可直接置 ""
说明:
bind 0.0.0.0只是允许容器内所有网卡监听,真正的外部隔离靠ports: 127.0.0.1+ 云防火墙,不要把 6379 发布到公网。protected-mode yes是第二道保险:无密码且非回环访问时直接拒绝。- 纯缓存场景可把
appendfsync everysec换no、甚至关掉持久化;当数据库用就保持 everysec。
五、启动与验证
cd /opt/redis
docker compose config -q
docker compose up -d
docker compose ps
验证密码与持久化:
# 未带密码必须被拒绝(应返回 NOAUTH)
docker exec redis7 redis-cli ping
# (error) NOAUTH Authentication required.
# 带密码正常
docker exec redis7 sh -c 'redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping'
# PONG
# 写一条数据,重启容器验证不丢
docker exec redis7 sh -c 'redis-cli -a "$REDIS_PASSWORD" --no-auth-warning set hello world'
docker compose restart redis
docker exec redis7 sh -c 'redis-cli -a "$REDIS_PASSWORD" --no-auth-warning get hello'
# "world"
# 确认监听只在回环
ss -ltnp | grep 6379
远程访问走 SSH 隧道:
ssh -L 6379:127.0.0.1:6379 user@203.0.113.10
redis-cli -h 127.0.0.1 -a '你的密码'
六、常用运维
# 实时查看命令
docker exec -it redis7 sh -c 'redis-cli -a "$REDIS_PASSWORD" --no-auth-warning'
# 内存与命中率
redis-cli -a "$REDIS_PASSWORD" info memory | grep used_memory_human
redis-cli -a "$REDIS_PASSWORD" info stats | grep -E 'keyspace_hits|keyspace_misses'
# 手动触发一次 AOF 重写 / RDB 备份
redis-cli -a "$REDIS_PASSWORD" BGREWRITEAOF
redis-cli -a "$REDIS_PASSWORD" BGSAVE
# 升级(数据在 bind mount,换 tag 后数据仍在;大版本升级先看 release notes)
docker compose pull && docker compose up -d
数据备份只需在低峰复制 data/ 目录前先 BGSAVE,或直接备份 AOF/RDB 文件;建议再同步到对象存储。
七、Redis 6 差异
老项目用 redis:6.0.16 时:
- 配置基本相同;
rename-command、AOF/RDB 指令一致。 - Redis 7 的 multipart AOF(
appendonlydir/)与 6 的单文件 AOF 格式不同,6→7 挂旧数据目录前先备份,让 7 自动完成升级转换,不要反向回挂。 - 6.x 已停止维护,仅建议在无法升级的遗留系统中锁定最后一个补丁版本。
八、常见问题
| 现象 | 原因与处理 |
|---|---|
容器启动即退出,日志 Permission denied |
data/logs 不是 999:999;chown -R 999:999 redis/data redis/logs |
| 健康检查不通过 | 密码里有特殊字符被 shell 截断;换 hex 密码,或确认 .env 与 --requirepass 一致 |
| 外网扫描到 6379、服务被刷 key | 端口绑了 0.0.0.0 且安全组放通。立刻改密码、检查 CONFIG get dir(排查写 crontab/公钥),改为回环绑定 |
| 内存打满、写入报 OOM | maxmemory + 淘汰策略已生效说明在正常淘汰;若策略是 noeviction 就会拒绝写,缓存场景用 allkeys-lru |
| AOF 文件越来越大 | 正常,达到阈值自动 rewrite;可低峰手动 BGREWRITEAOF,确认磁盘留足一倍空间 |
CONFIG 命令被改名后监控报错 |
改用别名,或监控走 exporter;安全加固与便利性按场景取舍 |
此处评论已关闭