用 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;安全加固与便利性按场景取舍
最后修改:2026 年 09 月 20 日
如果觉得我的文章对你有用,请随意赞赏