硬核实践:使用 Docker 部署生产级 Redis(持久化 + 安全配置 + 高可用)

Redis 容器化部署看起来简单,docker run redis 一条命令就能跑起来。但真到生产环境,问题全来了:数据丢了怎么办?被人扫端口挖矿了怎么防?内存爆了怎么处理?怎么做主从和哨兵?
这篇文章从最基础的 docker run 开始,一路讲到 Docker Compose、持久化策略、安全加固、主从复制、哨兵高可用,把生产环境用 Docker 部署 Redis 的整条链路讲透。
你能从这篇文章得到什么:

  • 三种部署方式的完整命令,复制就能用

  • RDB + AOF 持久化配置,数据不丢

  • 生产级安全加固方案,防挖矿防入侵

  • 主从复制 + 哨兵模式高可用部署

  • 常用运维命令 + 常见问题排查清单
    适合谁看:

  • 想把 Redis 跑起来的 Docker 新手

  • 一直在裸机装 Redis,想容器化迁移的运维

  • 会基础用法,但想搞清楚生产环境最佳实践的开发者

不废话,直接上干货。

一、环境准备

1.1 系统要求

bash 复制代码
# 检查 Docker 版本
docker --version
# Docker version 24.0.7, build afdd53b

# 检查 Docker Compose 版本
docker compose version
# Docker Compose version v2.21.0

1.2 前置检查

bash 复制代码
# 确认 6379 端口未被占用
netstat -tlnp | grep 6379
# 或
ss -tlnp | grep 6379

# 确认宿主机内存足够(Redis 是内存数据库)
free -h

注意:Redis 持久化时 fork 子进程需要额外内存,建议预留至少 50% 内存余量。


二、方式一:docker run 快速启动(适合测试)

2.1 拉取官方镜像

bash 复制代码
# 拉取最新稳定版
docker pull redis:latest

# 推荐:指定明确版本
docker pull redis:7.2-alpine

# 查看本地镜像
docker images | grep redis

选型建议

  • redis:alpine --- 体积小(~30MB),推荐生产使用
  • redis:latest --- 基于 Debian,体积大(~130MB),调试工具全
  • redis:7.2 --- 指定大版本,生产环境锁定版本

2.2 最简启动

bash 复制代码
docker run -d \
  --name redis \
  -p 6379:6379 \
  --restart=always \
  redis:7.2-alpine

2.3 带密码启动

bash 复制代码
docker run -d \
  --name redis \
  -p 6379:6379 \
  --restart=always \
  redis:7.2-alpine \
  redis-server --requirepass "your_strong_password"

2.4 验证连接

bash 复制代码
# 进入容器用 redis-cli 测试
docker exec -it redis redis-cli

# 带密码的情况
docker exec -it redis redis-cli -a "your_strong_password"
# 或进入后认证
127.0.0.1:6379> AUTH your_strong_password
OK

# 测试读写
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"

三、方式二:配置外置 + 数据卷持久化(生产标准)

最简启动只能用默认配置,数据存在容器里,删容器就没了。生产环境必须配置外置 + 数据持久化。

3.1 目录结构规划

bash 复制代码
# 创建 Redis 相关目录
mkdir -p /data/redis/{conf,data,logs}

表格

目录 用途
/data/redis/conf 配置文件 redis.conf
/data/redis/data 持久化数据(RDB + AOF)
/data/redis/logs 日志文件

3.2 配置文件 redis.conf

创建 /data/redis/conf/redis.conf

bash 复制代码
# ========== 基础配置 ==========
# 绑定地址,0.0.0.0 表示允许所有 IP 访问(生产环境建议绑定内网 IP)
bind 0.0.0.0

# 端口
port 6379

# 密码(生产环境必须设置强密码)
requirepass your_strong_password_here

# 数据库数量
databases 16

# 客户端连接数上限
maxclients 10000

# ========== 内存配置 ==========
# 最大内存(根据服务器实际情况设置,示例 2GB)
maxmemory 2gb

# 内存淘汰策略
# allkeys-lru:所有键中优先删除最近最少使用的
# allkeys-lfu:所有键中优先删除使用频率最低的
# volatile-lru:设置了过期时间的键中优先删除最近最少使用的
# noeviction:不淘汰,写满直接报错
maxmemory-policy allkeys-lru

# ========== 持久化 - RDB ==========
# 开启 RDB 持久化
save 900 1      # 900 秒内至少 1 个 key 变更
save 300 10     # 300 秒内至少 10 个 key 变更
save 60 10000   # 60 秒内至少 10000 个 key 变更

# RDB 文件名
dbfilename dump.rdb

# 数据目录
dir /data

# RDB 压缩
rdbcompression yes

# ========== 持久化 - AOF ==========
# 开启 AOF 持久化(推荐生产开启,RDB+AOF 混合模式)
appendonly yes

# AOF 文件名
appendfilename "appendonly.aof"

# AOF 刷盘策略
# always:每次写操作都刷盘(最安全,性能最差)
# everysec:每秒刷盘(推荐,平衡安全和性能)
# no:由操作系统决定刷盘时机(最快,最不安全)
appendfsync everysec

# AOF 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# ========== 日志配置 ==========
# 日志级别:debug、verbose、notice、warning
loglevel notice

# 日志文件
logfile "/data/redis.log"

# ========== 慢查询 ==========
# 慢查询阈值(微秒)
slowlog-log-slower-than 10000

# 慢查询最大记录数
slowlog-max-len 128

# ========== 安全加固 ==========
# 重命名危险命令(生产环境强烈建议)
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command KEYS ""
rename-command CONFIG "CONFIG_mysecret"
rename-command SHUTDOWN "SHUTDOWN_mysecret"

# 禁用危险命令(直接置空表示禁用)
# rename-command DEBUG ""

# ========== 其他 ==========
# 后台运行(Docker 部署不要开,否则容器会退出)
# daemonize no

# PID 文件
pidfile /var/run/redis.pid

重要 :Docker 部署 Redis 时,daemonize 必须设为 no(默认就是 no),否则容器启动后立即退出。

3.3 启动容器

bash 复制代码
docker run -d \
  --name redis \
  -p 6379:6379 \
  --restart=always \
  -v /data/redis/conf/redis.conf:/etc/redis/redis.conf:ro \
  -v /data/redis/data:/data \
  -v /data/redis/logs:/var/log/redis \
  --sysctl net.core.somaxconn=1024 \
  redis:7.2-alpine \
  redis-server /etc/redis/redis.conf

参数详解:

表格

参数 作用
-d 后台运行
--name redis 容器命名
-p 6379:6379 端口映射
--restart=always Docker 重启后自动启动
-v .../redis.conf:ro 配置文件只读挂载
-v .../data:/data 数据目录挂载,持久化数据存在这里
--sysctl net.core.somaxconn=1024 调大 TCP 连接队列,解决 Redis 启动警告
redis-server /etc/redis/redis.conf 指定配置文件启动

3.4 验证持久化

bash 复制代码
# 写入测试数据
docker exec -it redis redis-cli -a "your_password"
127.0.0.1:6379> set test_key test_value
OK
127.0.0.1:6379> save   # 手动触发 RDB 持久化
OK
127.0.0.1:6379> exit

# 查看数据文件
ls -la /data/redis/data/
# 应该能看到 dump.rdb 和 appendonly.aof 文件

# 重启容器验证数据不丢
docker restart redis
docker exec -it redis redis-cli -a "your_password" get test_key
# "test_value" --- 数据还在就说明持久化生效了

四、方式三:Docker Compose 部署(推荐)

生产环境统一用 Compose 管理,方便维护和迁移。

4.1 docker-compose.yml

bash 复制代码
version: '3.8'

services:
  redis:
    image: redis:7.2-alpine
    container_name: redis
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - ./conf/redis.conf:/etc/redis/redis.conf:ro
      - ./data:/data
      - ./logs:/var/log/redis
    command: redis-server /etc/redis/redis.conf
    sysctls:
      - net.core.somaxconn=1024
      - net.ipv4.tcp_max_syn_backlog=8192
    ulimits:
      nproc: 65535
      nofile:
        soft: 65535
        hard: 65535
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "your_strong_password_here", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 5s
    networks:
      - redis-network

networks:
  redis-network:
    driver: bridge

4.2 启动

bash 复制代码
# 前台启动看日志
docker compose up

# 后台启动
docker compose up -d

# 查看状态
docker compose ps

# 查看日志
docker compose logs -f redis

五、持久化策略详解

Redis 有两种持久化方式:RDB 和 AOF,生产环境建议都开(混合模式)。

5.1 RDB 快照

原理:每隔一段时间把内存中的数据全量快照写入磁盘。

优点

  • 文件紧凑,适合备份和灾备
  • 恢复速度快,直接加载 RDB 文件
  • 对性能影响小,fork 子进程写,主进程继续服务

缺点

  • 间隔时间内宕机会丢数据
  • 数据量大时 fork 耗时,可能造成短暂卡顿

配置

bash 复制代码
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir /data

5.2 AOF 追加文件

原理:把每一条写命令追加到文件末尾,类似 MySQL 的 binlog。

优点

  • 数据安全性高,最多丢 1 秒数据
  • 文件是文本格式,可读可手动修复

缺点

  • 文件体积比 RDB 大
  • 恢复速度比 RDB 慢
  • 写操作频繁时对性能有一定影响

配置

bash 复制代码
appendonly yes
appendfsync everysec   # 每秒刷盘,推荐
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

5.3 混合持久化(Redis 4.0+)

Redis 4.0 之后支持 RDB + AOF 混合模式,AOF 重写时把 RDB 内容写在 AOF 文件开头,后续增量写命令追加。兼顾了 RDB 的恢复速度和 AOF 的数据安全性。

bash 复制代码
# 开启混合持久化(Redis 5.0+ 默认开启)
aof-use-rdb-preamble yes

生产建议:RDB + AOF 混合模式,数据安全性和恢复速度兼顾。


六、安全配置(生产环境必做)

Redis 是被挖矿攻击的重灾区,裸奔的 Redis 公网暴露分分钟被入侵。以下安全措施必须做。

6.1 设置强密码

bash 复制代码
requirepass YourStrongPassword!@#2024

密码要够长够复杂,别用 123456redis 这种弱密码。

6.2 绑定内网 IP

如果只在内网使用,不要绑定 0.0.0.0

bash 复制代码
# 只允许内网访问
bind 192.168.1.100

或者干脆不映射端口,只通过 Docker 内部网络访问:

bash 复制代码
# docker-compose.yml 去掉 ports 配置,只暴露给内部网络
# ports:
#   - "6379:6379"

6.3 重命名 / 禁用危险命令

bash 复制代码
# 直接禁用
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command KEYS ""
rename-command DEBUG ""

# 重命名,只有知道别名的人能用
rename-command CONFIG "CONFIG_yoursecret"
rename-command SHUTDOWN "SHUTDOWN_yoursecret"
rename-command SAVE "SAVE_yoursecret"

6.4 防火墙限制

bash 复制代码
# 只允许特定 IP 访问 6379
iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 6379 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP

6.5 不要用 root 运行容器

bash 复制代码
# docker-compose.yml 中指定用户
user: "999:999"   # redis 用户的 uid/gid

6.6 安全检查清单

  • 设置了强密码
  • 没有绑定 0.0.0.0(或不映射公网端口)
  • 禁用 / 重命名了危险命令
  • 防火墙限制了访问来源
  • 容器不以 root 运行
  • Redis 版本是最新稳定版

七、高可用方案

7.1 主从复制

一主多从,主节点写,从节点读,读写分离。

docker-compose.yml
bash 复制代码
version: '3.8'

services:
  redis-master:
    image: redis:7.2-alpine
    container_name: redis-master
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - ./master/conf:/etc/redis
      - ./master/data:/data
    command: redis-server /etc/redis/redis.conf
    networks:
      - redis-net

  redis-slave1:
    image: redis:7.2-alpine
    container_name: redis-slave1
    restart: always
    ports:
      - "6380:6379"
    volumes:
      - ./slave1/conf:/etc/redis
      - ./slave1/data:/data
    command: redis-server /etc/redis/redis.conf --replicaof redis-master 6379
    depends_on:
      - redis-master
    networks:
      - redis-net

  redis-slave2:
    image: redis:7.2-alpine
    container_name: redis-slave2
    restart: always
    ports:
      - "6381:6379"
    volumes:
      - ./slave2/conf:/etc/redis
      - ./slave2/data:/data
    command: redis-server /etc/redis/redis.conf --replicaof redis-master 6379
    depends_on:
      - redis-master
    networks:
      - redis-net

networks:
  redis-net:
    driver: bridge
验证主从
bash 复制代码
# 主节点查看从节点信息
docker exec -it redis-master redis-cli info replication

# 主节点写数据
docker exec -it redis-master redis-cli set master_key hello

# 从节点读数据
docker exec -it redis-slave1 redis-cli get master_key
# "hello" --- 同步成功

7.2 哨兵模式(Sentinel)

主从复制的问题是主节点挂了需要手动切换。哨兵模式实现自动故障转移。

架构
  • 3 个 Sentinel 节点(奇数个,防止脑裂)
  • 1 主 2 从
  • Sentinel 监控主节点,主节点挂了自动选举新主
sentinel.conf
bash 复制代码
# 哨兵端口
port 26379

# 监控的主节点,名称、地址、端口、选举需要的票数
sentinel monitor mymaster redis-master 6379 2

# 主节点密码(如果有)
sentinel auth-pass mymaster your_password

# 主节点下线判断时间(毫秒)
sentinel down-after-milliseconds mymaster 5000

# 故障转移超时时间
sentinel failover-timeout mymaster 10000

# 同步新主节点的从节点数量
sentinel parallel-syncs mymaster 1
docker-compose.yml(哨兵部分)
bash 复制代码
  sentinel1:
    image: redis:7.2-alpine
    container_name: sentinel1
    restart: always
    ports:
      - "26379:26379"
    volumes:
      - ./sentinel1/conf:/etc/redis
    command: redis-sentinel /etc/redis/sentinel.conf
    depends_on:
      - redis-master
      - redis-slave1
      - redis-slave2
    networks:
      - redis-net

  sentinel2:
    image: redis:7.2-alpine
    container_name: sentinel2
    restart: always
    ports:
      - "26380:26379"
    volumes:
      - ./sentinel2/conf:/etc/redis
    command: redis-sentinel /etc/redis/sentinel.conf
    depends_on:
      - redis-master
    networks:
      - redis-net

  sentinel3:
    image: redis:7.2-alpine
    container_name: sentinel3
    restart: always
    ports:
      - "26381:26379"
    volumes:
      - ./sentinel3/conf:/etc/redis
    command: redis-sentinel /etc/redis/sentinel.conf
    depends_on:
      - redis-master
    networks:
      - redis-net
验证哨兵
bash 复制代码
# 查看哨兵状态
docker exec -it sentinel1 redis-cli -p 26379 sentinel master mymaster

# 查看从节点列表
docker exec -it sentinel1 redis-cli -p 26379 sentinel slaves mymaster

# 模拟主节点故障,观察自动切换
docker stop redis-master
# 等几秒后查看新主节点
docker exec -it sentinel1 redis-cli -p 26379 sentinel get-master-addr-by-name mymaster

7.3 集群模式(Cluster)

数据量大、需要水平扩展时用 Redis Cluster,数据分片存储在多个节点上。

注意:Redis Cluster 至少需要 6 个节点(3 主 3 从),单机部署只是测试用,生产环境要分布在不同机器上。


八、常用运维命令

8.1 容器操作

bash 复制代码
# 启动/停止/重启
docker start redis
docker stop redis
docker restart redis

# 进入容器
docker exec -it redis sh

# 查看实时日志
docker logs -f redis
docker logs -f --tail 100 redis

# 查看资源占用
docker stats redis

8.2 Redis 客户端命令

bash 复制代码
# 连接 Redis
docker exec -it redis redis-cli

# 带密码连接
docker exec -it redis redis-cli -a "your_password"

# 连接指定主机端口
docker exec -it redis redis-cli -h 127.0.0.1 -p 6379

8.3 信息查询

bash 复制代码
# 查看服务器信息
127.0.0.1:6379> info

# 查看内存使用
127.0.0.1:6379> info memory

# 查看持久化状态
127.0.0.1:6379> info persistence

# 查看复制信息
127.0.0.1:6379> info replication

# 查看慢查询
127.0.0.1:6379> slowlog get 10

# 查看 key 数量
127.0.0.1:6379> dbsize

8.4 持久化操作

bash 复制代码
# 手动触发 RDB 快照(阻塞式)
127.0.0.1:6379> SAVE

# 后台触发 RDB 快照(非阻塞)
127.0.0.1:6379> BGSAVE

# 手动触发 AOF 重写
127.0.0.1:6379> BGREWRITEAOF

# 查看最后一次持久化时间
127.0.0.1:6379> LASTSAVE

8.5 配置热修改

bash 复制代码
# 查看配置
127.0.0.1:6379> CONFIG GET maxmemory

# 修改配置(临时生效,重启失效)
127.0.0.1:6379> CONFIG SET maxmemory 4gb

# 把当前配置写入配置文件
127.0.0.1:6379> CONFIG REWRITE

九、常见问题与排错

Q1:容器启动后立即退出

大概率是配置文件里 daemonize yes 了,Docker 容器需要前台进程,改成 no

bash 复制代码
# 看日志确认原因
docker logs redis

Q2:启动警告 "WARNING overcommit_memory is set to 0"

bash 复制代码
# 临时解决
sysctl vm.overcommit_memory=1

# 永久解决,写入 /etc/sysctl.conf
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
sysctl -p

Q3:启动警告 "WARNING you have Transparent Huge Pages (THP) support enabled"

bash 复制代码
# 临时关闭
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 永久关闭,写入 rc.local
echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local
echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.local

Q4:启动警告 "WARNING: The TCP backlog setting of 511 cannot be enforced"

bash 复制代码
# 调大 somaxconn
sysctl net.core.somaxconn=1024

# docker run 时加参数
--sysctl net.core.somaxconn=1024

Q5:内存满了怎么办

bash 复制代码
# 查看内存使用情况
docker exec -it redis redis-cli info memory

# 查看大 key
docker exec -it redis redis-cli --bigkeys

# 清理过期 key
127.0.0.1:6379> SCAN 0 MATCH * COUNT 1000

# 检查内存淘汰策略是否合理
127.0.0.1:6379> CONFIG GET maxmemory-policy

Q6:RDB 持久化失败

检查数据目录权限,确保 redis 用户有写权限:

bash 复制代码
chown -R 999:999 /data/redis/data

十、性能优化建议

  1. 内存配置 :根据业务量设置 maxmemory,不要让 Redis 用到 swap
  2. 淘汰策略 :缓存场景用 allkeys-lruallkeys-lfu,比 volatile-lru 更稳妥
  3. 持久化策略:RDB + AOF 混合模式,平衡数据安全和性能
  4. 关闭 THP:透明大页会导致 Redis 延迟波动,必须关
  5. 内存大页 :开启 hugepage 可以减少页表开销,但要注意和 THP 区分
  6. 网络优化 :调大 somaxconntcp_backlog
  7. 慢查询监控:开启慢查询日志,定期排查慢命令
  8. 连接池:客户端使用连接池,避免频繁创建销毁连接
  9. pipeline:批量操作使用 pipeline,减少网络往返
  10. key 设计:避免大 key、热 key,合理设置过期时间

总结

Docker 部署 Redis 三步走:

  1. 测试环境docker run 快速启动,验证功能
  2. 生产环境:配置外置 + 数据卷持久化 + 安全加固
  3. 高可用:主从复制 + 哨兵模式,实现自动故障转移

核心原则:数据持久化、密码必设、危险命令禁用、公网不裸奔、内存有上限

相关推荐
weixin_471383031 小时前
Docker - 05 - 构建流程
运维·docker·容器
宠友信息3 小时前
多端数据互通场景下Spring Boot仿小红书源码结构设计
数据库·spring boot·redis·缓存·架构
长不胖的路人甲3 小时前
Redis 缓存的数据持久化方案讲解
数据库·redis·缓存
长不胖的路人甲3 小时前
Redis 单线程为什么速度很快
数据库·redis·缓存
彦为君4 小时前
算法思维与经典智力题
java·前端·redis·算法
ejinxian5 小时前
微虚拟机 smolvm 与Docker 容器比较
运维·docker·容器·smolvm
彦为君5 小时前
Redis最新版本特性
java·数据库·redis·算法·bootstrap
爱码少年5 小时前
Docker如何一次查看多个容器日志
运维·docker·容器
长不胖的路人甲6 小时前
Redis 数据删除策略
数据库·redis·spring