Docker部署Redis 7实战:从单机到主从哨兵架构
2026/9/24 18:26:22 网站建设 项目流程

很多朋友第一次接触 Docker 部署 Redis,都是先搜到一条docker run redis命令,敲完发现确实能跑,但一重启数据没了、配置文件改不了、容器日志刷到飞起也不知道怎么管,最后只能把容器删了重建。这篇文章我就用 Redis 7 作为例子,把从环境准备、镜像选择、配置文件挂载、数据持久化、Compose 编排到主从哨兵扩展的完整链路都走一遍,中间会穿插我在实际部署中踩过的坑和排障思路,希望能帮你把 Docker 部署 Redis 这件事彻底吃透。

这篇文章的前半部分会花不少篇幅讲 Docker 环境本身,包括 Windows 上 Docker Desktop 最常见的启动失败问题、镜像下载慢的解决办法,因为这些都是新手极容易卡住的地方。后半部分进入 Redis 7 的实际部署,会给出可以直接抄作业的docker run命令、redis.conf配置方法、docker-compose.yml完整文件,以及主从哨兵架构的搭建思路。适合刚接触 Docker 的开发者,也适合那些已经能跑通单机 Redis、但想理解背后原理的运维和测试同学。

1. 环境准备:先把 Docker 本身跑稳

1.1 Windows 上 Docker Desktop 启动失败的常见原因

很多 Windows 用户第一关就挂在 Docker Desktop 启动上,最常见的报错是Virtualization support not detected或者Docker Desktop failed to start because virtualisation support wasn't detected。这个问题的本质是 Docker Desktop 在 Windows 上依赖两个底层组件:WSL2 和 BIOS 里的虚拟化开关。我之前帮同事排查过一台机器,装完 Docker Desktop 点了半天启动都没反应,最后发现是 BIOS 里的 Intel VT-x 根本没开。

先看 WSL2 状态,在 PowerShell 里执行wsl --status,如果提示没有安装发行版或者 WSL 内核版本太老,就先执行wsl --update。如果系统提示“虚拟化支持未检测到”,重启进 BIOS,找到 Intel Virtualization Technology 或 AMD SVM Mode,把它设为 Enabled 再重启系统。还有一个容易被忽略的点,Windows 的“虚拟机平台”和“适用于 Linux 的 Windows 子系统”这两个可选功能必须同时开启,在“启用或关闭 Windows 功能”里勾选后重启才行。

确认这些之后,再打开 Docker Desktop,如果还是起不来,可以去看日志。Docker Desktop 的日志路径在%LOCALAPPDATA%\Docker\log,里面会有hostdocker两个子目录。常见场景是 WSL2 内核版本过旧导致 Docker 引擎无法通信,报错信息里会出现failed to connect to the docker api at npipe:////./pipe/dockerDesktopLinuxEngine,这种就执行一下wsl --update把内核更新到最新版,基本都能解决。

1.2 Linux 服务器安装 Docker 的最稳路径

如果在 Linux 服务器上部署,建议走 Docker 官方仓库安装,而不是用系统自带的旧版本。我见过不少生产环境因为用了发行版自带的 docker 包,版本太老导致部分新特性不支持,后面维护起来很麻烦。以 Ubuntu 为例,先安装依赖包,然后添加 Docker 官方的 GPG key 和仓库,再执行安装。

sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

装完执行sudo systemctl enable --now docker让服务开机自启。这里我特别提醒一句,国内服务器如果直接访问 Docker Hub 拉镜像,速度和稳定性都不太乐观,建议在/etc/docker/daemon.json里配置镜像加速器,具体配置方式我放到下一节一起讲。

1.3 镜像下载慢的根治方案

无论 Windows 还是 Linux,镜像下载慢都是新手吐槽最多的点。在daemon.json里配置 registry mirror 是 Docker 官方支持的加速方式,配置文件路径在 Linux 是/etc/docker/daemon.json,Windows 上可以通过 Docker Desktop 的 Settings 里的 Docker Engine 选项卡直接编辑。

{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://dockerproxy.com" ] }

配置完重启 Docker。注意这个文件里已经存在的内容不要覆盖,如果之前配置过>docker run -d --name redis7-test -p 6379:6379 redis:7.2.4

然后执行docker ps看容器状态,如果显示 Up 就没问题。再用docker exec -it redis7-test redis-cli ping,返回 PONG 就说明 Redis 进程正常工作。这个过程中如果出现端口占用错误,一般是你本机已经有一个 Redis 在跑,可以换一个端口或者先停掉本机 Redis。

验证完把容器删掉,后面我们开始配置正式部署:docker stop redis7-test && docker rm redis7-test

3.2 挂载配置文件:把 Redis 调到可用的关键一步

最简容器可以用,但绝对不能用。正式部署的第一步是准备一个自己的 redis.conf。我习惯先创建目录结构,把配置文件和后续的持久化数据分开放:

mkdir -p /opt/redis7/{conf,data}

然后在/opt/redis7/conf/redis.conf里写入核心配置。这里我不会贴一份几百行的完整配置,而是给一份能覆盖绝大多数场景的浓缩版:

bind 0.0.0.0 port 6379 protected-mode yes requirepass yourStrongPassword123 daemonize no dir /data appendonly yes appendfsync everysec maxmemory 256mb maxmemory-policy allkeys-lru logfile ""

逐项解释一下我的选择。bind 0.0.0.0让 Redis 监听所有网卡,配合protected-mode yesrequirepass才能既保证容器端口映射可用,又不会裸奔在网络上。daemonize no必须设置,因为 Docker 容器需要前台进程,如果设置成 yes,容器启动后 Redis 会后台运行,容器会立刻退出。dir /data对应镜像的 VOLUME 声明,持久化文件会写在这里。appendonly yes开启 AOF 持久化,appendfsync everysec是性能和可靠性的平衡点。maxmemorymaxmemory-policy是为防止 Redis 内存撑爆宿主机,建议根据业务数据量预留 20% 到 30% 余量。

配置好之后,用挂载方式启动:

docker run -d \ --name redis7 \ -p 6379:6379 \ -v /opt/redis7/conf/redis.conf:/usr/local/etc/redis/redis.conf:ro \ -v /opt/redis7/data:/data \ redis:7.2.4 \ redis-server /usr/local/etc/redis/redis.conf

注意这里镜像名后面带了redis-server /usr/local/etc/redis/redis.conf,这是覆盖了镜像默认的 CMD,告诉容器用我们挂载进去的配置启动。-v宿主机路径和容器路径之间用冒号隔开,后面加:ro表示只读挂载配置文件,防止容器内误修改。启动后验证:docker exec -it redis7 redis-cli -a yourStrongPassword123 ping,返回 PONG 就说明配置生效了。

3.3 数据持久化的原理与实测验证

Redis 的持久化有两个机制,RDB 是定期生成内存快照,AOF 是追加每一条写命令。生产环境通常两者都开,RDB 用于快速恢复大数据集,AOF 用于尽可能减少数据丢失。我在配置文件里开启了appendonly yes,所以容器data目录里会持续生成 AOF 文件。

实测一下持久化是否生效。先往 Redis 里写一条数据:docker exec -it redis7 redis-cli -a yourStrongPassword123 set user:1 zhangsan,拿到 OK 后执行docker restart redis7,重启完再get user:1,如果能拿到 zhangsan 说明 AOF 持久化已经生效了。这里有个小技巧,可以顺便看一眼/opt/redis7/data/目录下的appendonly.aof文件大小变化,理解 AOF 是持续追加写入的。如果数据量大,还会出现多个 aof 文件前缀的文件,这是 AOF 重写机制在自动压缩历史命令,属于正常现象。

3.4 容器时区和日志的问题

镜像默认时区是 UTC,这会导致日志时间戳和业务时间戳与本地时间不一致。如果只是本地测试可能无所谓,但生产环境排查问题时日志差 8 小时很让人抓狂。解决办法是在启动容器时挂载宿主机时区文件:

-v /etc/localtime:/etc/localtime:ro

还有一种做法是在配置里设置logfile指向标准输出,让 Docker 统一管理日志。我在上面配置文件里写的是logfile "",意思是让 Redis 把日志输出到标准输出,然后通过docker logs redis7查看。这样日志会进入 Docker 的日志驱动,配合docker logs --since 5m redis7查看最近五分钟日志很方便。如果日志量很大,记得在 daemon.json 里配置 log rotation,比如log-driver: json-file配合max-size: 10mmax-file: 3,防止日志文件无限增长把磁盘打满。

4. 用 Docker Compose 编排 Redis 服务

4.1 为什么单独用 docker run 不够

单机测试用docker run已经够了,但如果你的项目里不止一个容器,或者需要为不同环境重复部署,再用长串的 docker run 命令就很容易出错。Docker Compose 的核心价值是把容器定义写成声明式文件,提交到 Git 里做版本管理,换一台机器执行docker compose up -d就能恢复同样的环境。

Redis 单独部署用 Compose 可能显得有点杀鸡用牛刀,但很多后端的项目结构是 Nginx + MySQL + Redis + 应用服务四个容器,用 Compose 管理这四个服务,是比较推荐的方案。下面我给出一个 redis7 的 compose 文件,既适用于单机部署,也为后续主从扩展留下了位置。

4.2 编写 docker-compose.yml 实战

创建/opt/redis7/docker-compose.yml

version: "3.8" services: redis: image: redis:7.2.4 container_name: redis7 restart: always ports: - "6379:6379" volumes: - ./conf/redis.conf:/usr/local/etc/redis/redis.conf:ro - ./data:/data command: ["redis-server", "/usr/local/etc/redis/redis.conf"] environment: - TZ=Asia/Shanghai sysctls: - net.core.somaxconn=1024 ulimits: nproc: 65535 nofile: soft: 100000 hard: 100000

这个文件里我特意加了几个值得说明的配置。restart: always让容器在异常退出或宿主机重启后自动拉起,这是生产环境必须的兜底。environment里的TZ=Asia/Shanghai是另一种设置时区的方式,比挂载 /etc/localtime 更容器化。sysctlsulimits这两个配置是应对高并发场景下 Redis 报accept tcp listener: accept4: too many open files或者 backlog 队列溢出问题的,默认值偏保守,调大后能支撑更高的连接数。

启动和验证命令:

cd /opt/redis7 docker compose up -d docker compose ps docker compose logs -f redis

这里要提醒一下,不同版本的 docker compose 子命令不一样,老版本是docker-compose,新版本集成进了 docker CLI 是docker compose(中间没有横杠)。如果你安装的是 docker-compose-plugin,直接使用docker compose;如果老项目用的是独立的 docker-compose 二进制,需要下载对应版本。

5. 从单机到高可用:Redis 主从哨兵架构

5.1 主从复制的基本概念

单机 Redis 如果挂了,整个依赖缓存的业务都会受影响。最基础的保障方案是主从复制,一个主节点负责读写,一个或多个从节点同步主节点的数据,主节点挂了之后应用可以切到从节点读取。如果用上 Sentinel 哨兵,主节点故障时哨兵会自动把某个从节点提升为主节点,实现高可用。

Docker 部署主从复制,核心仍然是配置文件挂载。我先演示最简单的一主一从架构。假设宿主机两个端口:6379 给主节点,6380 给从节点。主节点配置和之前一样,从节点配置里加一段复制配置:

replicaof redis-master 6379 masterauth yourStrongPassword123 replica-read-only yes

注意在 Redis 7 里,slaveof这个旧名词已经被replicaof取代了,虽然旧配置还能兼容,但新项目建议直接用新命令。masterauth是必须的,如果主节点开启了 requirepass,从节点不知道认证密码就无法完成同步。

5.2 用 Compose 搭建主从哨兵集群

主从复制的扩展用 Compose 来编排会清晰很多。我直接给一个三节点的配置提纲,主节点 6379、从节点 6380、哨兵节点 26379:

version: "3.8" services: redis-master: image: redis:7.2.4 container_name: redis-master restart: always ports: - "6379:6379" volumes: - ./master/conf/redis.conf:/usr/local/etc/redis/redis.conf:ro - ./master/data:/data command: ["redis-server", "/usr/local/etc/redis/redis.conf"] redis-slave: image: redis:7.2.4 container_name: redis-slave restart: always depends_on: - redis-master ports: - "6380:6379" volumes: - ./slave/conf/redis.conf:/usr/local/etc/redis/redis.conf:ro - ./slave/data:/data command: ["redis-server", "/usr/local/etc/redis/redis.conf"] redis-sentinel: image: redis:7.2.4 container_name: redis-sentinel restart: always depends_on: - redis-master - redis-slave ports: - "26379:26379" volumes: - ./sentinel/conf/sentinel.conf:/usr/local/etc/redis/sentinel.conf:ro command: ["redis-sentinel", "/usr/local/etc/redis/sentinel.conf"]

哨兵配置sentinel.conf最核心的三行:

sentinel monitor mymaster redis-master 6379 1 sentinel auth-pass mymaster yourStrongPassword123 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000

monitor后面的数字 1 表示最少需要 1 个哨兵同意才能判定主节点故障并触发故障转移。测试环境设 1,生产环境至少设 2 或 3,避免哨兵自身误判。这里有个坑,主从容器之间通过 compose 网络访问时,主节点地址不能写 127.0.0.1,而要写 service 名称redis-master,因为 Compose 会为服务做 DNS 解析。这也是为什么很多人在 Docker 里配主从复制不成功的原因:配置文件里写的地址是宿主机视角的 localhost,但容器内部的 localhost 是容器自己。

启动后用docker exec -it redis-slave redis-cli -p 6379 -a yourStrongPassword123 info replication查看从节点状态,如果role:slavemaster_link_status:up,说明主从链路已经通了。

6. 常见问题与排障技巧实录

6.1 问题速查表

这里整理一份我在实际部署中遇到的典型问题和排查方向,按出现频率排序:

现象可能原因排查与解决
容器启动后立即退出配置里 daemonize 被设为 yes检查配置文件,改为 daemonize no
客户端连接被拒绝Redis 未监听预期网卡检查 bind 配置和 protected-mode 是否冲突
认证失败requirepass 与客户端密码不一致docker exec进入容器查看配置实际值
持久化文件没生成dir 路径不可写或权限不对查看 data 目录权限,确保 UID 999 有写权限
主从同步失败配置文件 master 地址写成了 localhost改为 compose service 名称或宿主机 IP
日志时间差 8 小时容器时区是 UTC加 TZ 环境变量
镜像拉取超时未配置镜像加速器配置 registry-mirrors 并重启 Docker
docker compose 命令不存在安装了旧版独立二进制改用docker-compose或安装 compose plugin

6.2 日志分析和容器内调试思路

容器服务的排障思路和一个关键原则:不要直接在生产容器里乱改配置然后docker restart,这不是一个可复现的操作。正确的做法是:docker logs看实时日志,如果日志不够详细,就用docker exec -it redis7 sh进入容器内部,直接执行redis-cli命令测试。

比如有一次我排查主从同步失败,docker logs redis-slave里只看到MASTER <-> REPLICA sync started,没有更多信息。进入容器执行redis-cli -a password info replication,可以看到master_link_down_since_seconds和最后一条同步错误信息,错误指向认证失败。检查发现从节点配置里masterauth忘记填写,补上之后重启从节点就恢复正常了。

还有一次是排查持久化问题,AOF 文件一直不增长。我先检查CONFIG GET dir返回的是/data,再检查/data目录权限,发现宿主机的 data 目录属主是 root,而容器内 redis 用户 UID 999 没有写权限。解决方法很简单:chown -R 999:999 /opt/redis7/data,这个问题在 Linux 服务器上特别常见,Windows 上因为权限模型不同很少遇到。

6.3 端口映射和防火墙的坑

部署完成后,如果外部机器连不上 Redis,先别急着怀疑 Redis 配置。按这个顺序排查:先在本机执行docker ps确认端口映射在,然后执行telnet 服务器IP 6379看端口是否通。如果不通,再看云服务商的安全组规则和宿主机防火墙。

很多云服务器默认有安全组策略,即使容器端口映射正确,安全组没放行 6379 端口,外部还是连不上。在测试环境中为了省事,有人会直接关掉防火墙,但生产环境建议只放行必要的端口,并且尽量不要把 Redis 6379 直接暴露到公网。更好的做法是让应用和 Redis 处在同一个内网或 Docker 网络里,连接时走内部网络地址,不经过宿主机端口映射。

7. 生产环境实战体会与扩展方向

7.1 我在实际应用中体会最深的三件事

部署 Redis 7 本身不难,真正决定部署质量的是细节。第一个体会是配置文件必须有版本管理。我见过很多团队只在服务器上手动改 redis.conf,几个月后想回滚都不知道改动过什么。建议把 redis.conf 和 docker-compose.yml 都放进 Git,每次变更都留痕,出问题能快速 diff。

第二个体会是 Redis 的内存规划一定要提前做。容器没有直观的内存限制时,Redis 会一直吃掉宿主机内存直到触发 OOM,到时候 Docker 引擎和其他容器全部遭殃。我在生产环境的做法是:宿主机内存 16G,给 Redis 容器限制 4G,maxmemory设置 3G,maxmemory-policyallkeys-lru。这样 Redis 即使遇到缓存穿透或者异常流量,也只会淘汰 key 而不是拖垮整个宿主机。

第三个体会是监控必须配套。单靠docker ps看容器活着不等于 Redis 在正常服务。从 Redis 7.0 开始,官方提供的redis-cli --stat可以实时查看 ops、hit rate、memory 等指标,redis-cli --latency能测客户端到服务器的延迟。我一般会建议至少用docker stats配合redis-cli info all定期采集数据,能发现很多潜在的容量瓶颈。

7.2 后续还能扩展的方向

这篇文章覆盖的是 Redis 在 Docker 里的标准部署方式,但实际生产环境还有几个方向值得继续深入:

  • Redis 集群模式,也就是 Redis Cluster,适合单节点内存已经无法满足业务需求的场景,数据自动分片到多个节点。
  • 自定义 Dockerfile 封装 Lua 扩展或第三方模块,比如 RediSearch、RedisJSON,镜像构建时把模块编译进去。
  • 与 Kubernetes 结合,利用 Helm Chart 部署 Redis Operator,实现自动故障转移和存储卷管理。
  • Redis 7 新特性,包括 AOF 文件碎片整理、Sharded Pub/Sub、Function 脚本引擎,这些在 Docker 部署后都能直接体验。

最后再把一个小技巧也一起放这儿:如果容器已经启动,突然想改某个配置项,不用重建容器,可以先docker exec -it redis7 redis-cli -a 密码 CONFIG SET 配置项 值动态修改,再配合CONFIG REWRITE把修改写入配置文件。但动态修改只适合临时调整,最终的配置还是要改宿主机上的 redis.conf 和 compose 文件,再重建容器让配置状态与代码仓库保持同步。这个习惯养成了,线上维护 Redis 会省下很多不必要的麻烦。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询