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
密码要够长够复杂,别用
123456、redis这种弱密码。
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
十、性能优化建议
- 内存配置 :根据业务量设置
maxmemory,不要让 Redis 用到 swap - 淘汰策略 :缓存场景用
allkeys-lru或allkeys-lfu,比volatile-lru更稳妥 - 持久化策略:RDB + AOF 混合模式,平衡数据安全和性能
- 关闭 THP:透明大页会导致 Redis 延迟波动,必须关
- 内存大页 :开启
hugepage可以减少页表开销,但要注意和 THP 区分 - 网络优化 :调大
somaxconn和tcp_backlog - 慢查询监控:开启慢查询日志,定期排查慢命令
- 连接池:客户端使用连接池,避免频繁创建销毁连接
- pipeline:批量操作使用 pipeline,减少网络往返
- key 设计:避免大 key、热 key,合理设置过期时间
总结
Docker 部署 Redis 三步走:
- 测试环境 :
docker run快速启动,验证功能 - 生产环境:配置外置 + 数据卷持久化 + 安全加固
- 高可用:主从复制 + 哨兵模式,实现自动故障转移
核心原则:数据持久化、密码必设、危险命令禁用、公网不裸奔、内存有上限。