CentOS 7 上用 Docker 快速搭建 Redis 集群实战 简介面向需要在 CentOS 7.x 环境下快速搭建 Redis 集群的运维与开发人员这份资源提供了一套基于 Docker 的一键部署方案通过 shell 脚本把镜像导入、容器编排与配置生成等环节串联起来减少手工逐台配置的重复劳动适合具备基础 Linux 与容器操作经验、希望快速验证集群可用性的读者。压缩包共 6 个文件以 sh 脚本为主体配合 tar 镜像包、conf 配置文件与 md 说明文档整体约 22.46MB脚本、镜像与配置各司其职按说明传入参数即可自动执行部署流程。目前已有 1055 人学习下载说明该方案在实际环境中具备一定参考价值。读者可获得可直接复用的自动化部署脚本、预置镜像与集群配置样例以及卸载脚本和说明文档便于在测试或预发环境中快速拉起集群、验证节点通信与主从关系并据此理解脚本参数传递与部署逻辑为后续排错和二次调整提供依据。1. 在 CentOS 7 上装 Redis 集群为什么我坚持用 Docker 而不是源码编译上周帮一个朋友救火他照着某篇教程在 CentOS 7 上源码编译 Redis 集群六个节点编译完启动cluster meet死活握不上手日志里全是Unable to connect to node。折腾到凌晨两点最后发现是 firewalld 把 16379 集群总线端口拦了而他一直以为只要开 6379 就够了。这种坑在 CentOS 7 上太常见了——系统自带的老内核、老 glibc、默认开着的 firewalld、还有那个让人又爱又恨的 SELinux任何一个没伺候好集群就起不来。所以我自己在 CentOS 7.x 上搭 Redis 集群一律走 Docker shell 脚本这条路。原因很实在CentOS 7 的 yum 源里 Redis 版本常年停在 3.2想上 5.x、6.x 就得自己编译编译又要处理 gcc 版本、jemalloc、systemd 单元文件一堆事而 Docker 镜像把运行时依赖全打包好了宿主机只需要装个 Docker剩下的端口映射、数据目录、配置文件全交给脚本统一生成。这套方案特别适合两类人一是手上只有 CentOS 7 老机器、又不想动系统底层的运维二是需要反复重建测试集群、追求「一条命令拉起六个节点」的开发者。装不好的后果也很直接——节点互相看不见、槽位分配失败、CLUSTERDOWN报错刷屏而这些问题九成都能在安装阶段规避掉。2. 装前把环境钉死CentOS 7.x 的 Docker 与内核准备2.1 版本对照别让 Docker 版本成为第一个坑CentOS 7.x 的生命周期决定了它能装的 Docker 版本有上限。我一般不去追最新的 Docker CE而是锁在20.10.x这个长期维护线上它对 CentOS 7 的内核3.10兼容性最稳docker-ce-cli和containerd.io的依赖关系也不会打架。Redis 镜像则选redis:6.2-alpinealpine 版体积小、启动快6.2 是最后一个支持 CentOS 7 老内核无痛运行的稳定大版本7.x 镜像在部分老机器上会因为io_uring相关特性报错。组件推荐版本说明操作系统CentOS 7.6 ~ 7.97.9 最省心7.6 需确认内核补丁Docker Engine20.10.24别用 23.xCentOS 7 上 cgroup 驱动易出问题Redis 镜像redis:6.2-alpine6.2 稳定alpine 体积约 30MB集群规模3 主 3 从6 个节点端口 7001~7006先确认系统底子。内核版本低于 3.10 的比如某些精简版 7.2建议先yum update kernel并重启否则 Docker 的 overlay2 存储驱动可能起不来。执行下面几条命令把现状摸清# 查看内核与系统版本确认在 3.10 以上、CentOS 7.x uname -r cat /etc/centos-release # 检查是否已有旧版 docker有就先卸干净 yum list installed | grep -i docker # 确认 firewalld 和 SELinux 状态后面要针对性处理 systemctl status firewalld getenforce这几条不是走过场。uname -r出来如果是3.10.0-514这种早期版本overlay2 会有兼容问题getenforce返回Enforcing的话后面挂载数据目录时容器可能读不到配置得提前规划是关掉还是加:z标签。我一般图省事测试环境直接setenforce 0并把/etc/selinux/config改成disabled生产环境则老老实实给挂载目录打 SELinux 上下文。2.2 安装 Docker用官方源还是阿里云镜像源CentOS 7 默认的extras源里有个叫docker的老包1.13 版本千万别装那个它和 Docker CE 是两码事。正确做法是加 Docker 官方仓库国内机器为了速度换成阿里云镜像源。下面这套是我用了很多次的顺序# 1. 装依赖工具 yum install -y yum-utils device-mapper-persistent-data lvm2 # 2. 添加 Docker CE 仓库这里用阿里云镜像加速下载 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 3. 安装指定版本的 Docker避免自动升到不兼容的新版 yum install -y docker-ce-20.10.24 docker-ce-cli-20.10.24 containerd.io # 4. 启动并设开机自启 systemctl enable docker systemctl start docker # 5. 验证 docker version第 3 步锁版本是关键。如果不写版本号直接yum install docker-ceyum 会拉最新版而 23.x 之后 Docker 对 cgroup v1 的支持在 CentOS 7 上时有抖动表现为容器启动后立刻退出、docker logs里报failed to create shim。锁在 20.10.24 能避开这一整类玄学问题。第 5 步docker version要能看到 Client 和 Server 两段都正常输出如果 Server 段报Cannot connect to the Docker daemon多半是没启动或者当前用户不在 docker 组systemctl status docker看具体原因。装完 Docker 还有一步容易被忽略配置镜像加速和日志驱动。在/etc/docker/daemon.json里写{ registry-mirrors: [https://docker.mirrors.ustc.edu.cn], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 } }registry-mirrors换成你能用的加速地址拉 redis 镜像会快很多log-opts限制单个容器日志不超过 100MB、最多留 3 个不然集群跑几天日志能把磁盘塞满——这是我在一台跑了半年的测试机上真实踩过的坑/var/lib/docker涨到 40G 才发现。改完systemctl daemon-reload systemctl restart docker生效。2.3 网络与端口规划集群总线端口才是重灾区Redis 集群每个节点要开两个端口客户端端口比如 7001和集群总线端口客户端端口 10000即 17001。很多人只映射了 7001 忘了 17001结果cluster meet永远超时。用 Docker 跑的时候-p参数必须两个都映射而且容器内redis.conf里的cluster-announce-bus-port要和映射出去的一致。我一般把六个节点规划成 7001~7006对应总线端口 17001~17006全部映射到宿主机。firewalld 如果开着要么直接systemctl stop firewalld测试环境要么把这段端口段放行# 放行 7001-7006 和 17001-17006 两段端口 firewall-cmd --permanent --add-port7001-7006/tcp firewall-cmd --permanent --add-port17001-17006/tcp firewall-cmd --reload这里有个细节Docker 的端口映射走的是 iptables 的DOCKER链理论上 firewalld 的规则管不到它但 CentOS 7 上 firewalld 和 docker 的 iptables 规则经常互相覆盖重启 docker 后 firewalld 规则可能失效。所以我的习惯是测试环境直接关 firewalld生产环境用firewall-cmd放行后systemctl restart docker再firewall-cmd --reload顺序别反。端口规划清楚了后面脚本里就是照着这个表填参数不会乱。3. 用 shell 脚本拉起六个节点目录、配置、容器一条龙3.1 脚本整体结构一个变量区管住所有可变参数这套脚本我拆成三块变量定义区、配置生成函数、容器启动循环。变量区把所有会变的东西集中改集群规模、改端口、改密码只动这一处。核心变量大概长这样#!/bin/bash # redis-cluster-deploy.sh # 用途在 CentOS 7.x 上用 Docker 一键拉起 Redis 6.2 三主三从集群 # 可变参数区 REDIS_IMAGEredis:6.2-alpine # 镜像版本锁死避免漂移 BASE_PORT7001 # 起始客户端端口 NODE_COUNT6 # 节点总数3主3从 DATA_ROOT/data/redis-cluster # 宿主机数据根目录 REDIS_PASSYourStrongPass123 # 集群密码生产必须改 NET_NAMEredis-cluster-net # 自定义 bridge 网络名BASE_PORT和NODE_COUNT决定了循环生成 7001~7006 六个节点DATA_ROOT下每个节点一个子目录存redis.conf和持久化文件NET_NAME是自定义网络让六个容器能通过容器名互相解析——这点很重要用默认 bridge 网络的话容器间只能用 IP 通信节点重启 IP 变了集群就乱。密码这块6.x 集群要求所有节点密码一致且masterauth和requirepass都要设脚本里统一用REDIS_PASS注入。3.2 生成 redis.conf集群模式的关键五项每个节点的配置文件不能照搬单机版集群模式有几个必改项。脚本里用 heredoc 生成核心片段# 为第 i 个节点生成配置port 为对应客户端端口 generate_conf() { local port$1 local dir$2 cat ${dir}/redis.conf EOF port ${port} bind 0.0.0.0 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 127.0.0.1 cluster-announce-port ${port} cluster-announce-bus-port $((port 10000)) appendonly yes requirepass ${REDIS_PASS} masterauth ${REDIS_PASS} daemonize no EOF }逐项说下为什么这么写。cluster-enabled yes是集群开关不开这个后面cluster meet直接报错cluster-config-file nodes.conf是节点自己维护的集群状态文件必须可写所以数据目录要挂对cluster-node-timeout 5000是故障判定时间5 秒对测试环境够用生产可以调到 15000 减少误判cluster-announce-ip这里填127.0.0.1是因为所有节点在同一台宿主机、通过端口映射对外如果你的节点跨机器部署这里要填宿主机真实 IPcluster-announce-bus-port用port 10000自动算和前面端口规划对上appendonly yes开 AOF 持久化集群环境建议开不然重启丢数据后槽位状态可能对不上daemonize no是因为容器里必须前台运行写 yes 容器会立刻退出。提示protected-mode no在容器内是必须的因为容器网络对 Redis 来说算「非本地回环」不关保护模式会拒绝外部连接。但这也意味着密码必须设requirepass那行别偷懒删掉。3.3 启动容器端口映射、数据挂载、网络三件套配置生成完循环起容器。每个节点的docker run参数是重点# 创建自定义网络已存在则忽略报错 docker network create ${NET_NAME} 2/dev/null for i in $(seq 0 $((NODE_COUNT - 1))); do port$((BASE_PORT i)) node_dir${DATA_ROOT}/${port} mkdir -p ${node_dir} generate_conf ${port} ${node_dir} docker run -d \ --name redis-${port} \ --network ${NET_NAME} \ -p ${port}:${port} \ -p $((port 10000)):$((port 10000)) \ -v ${node_dir}:/data \ -v ${node_dir}/redis.conf:/usr/local/etc/redis/redis.conf \ ${REDIS_IMAGE} \ redis-server /usr/local/etc/redis/redis.conf done-p两行分别映射客户端端口和总线端口少一行集群就组不起来-v第一行把数据目录挂进去nodes.conf和 AOF 文件都落在这里容器删了数据还在第二行把配置文件挂进去改配置不用进容器。--network指定自定义网络六个容器同网段后面cluster meet用容器名或 IP 都行。镜像后面跟的redis-server /usr/local/etc/redis/redis.conf是覆盖默认启动命令让 Redis 读我们生成的配置而不是镜像自带的默认配置——这一步漏了的话容器起来是单机模式cluster-enabled根本没生效。启动完docker ps应该看到六个容器都是Up状态。如果有容器反复重启docker logs redis-7001看报错最常见的是配置文件路径挂载错了导致 Redis 找不到 conf、或者nodes.conf所在目录没写权限。数据目录我一般chmod 777图省事生产环境按 Redis 容器内 uid 来设更规范。3.4 创建集群与分配槽位redis-cli --cluster 的正确用法六个节点都起来后用redis-cli --cluster create一次性组集群。这条命令要在某个容器内执行或者宿主机装了 redis-cli 也行# 在第一个容器内执行集群创建3 主 3 从由 --cluster-replicas 1 自动分配 docker exec -it redis-7001 redis-cli -a ${REDIS_PASS} --cluster create \ 172.18.0.2:7001 172.18.0.3:7002 172.18.0.4:7003 \ 172.18.0.5:7004 172.18.0.6:7005 172.18.0.7:7006 \ --cluster-replicas 1这里 IP 要换成你环境里六个容器的实际内网 IP用docker inspect -f {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}} redis-7001逐个查。--cluster-replicas 1表示每个主节点配一个从节点6 个节点正好 3 主 3 从。命令执行后会列出主从分配方案输入yes确认。如果卡在Waiting for the cluster to join九成是总线端口没通——回到 2.3 检查-p映射和 firewalld。槽位分配是这条命令自动做的16384 个槽平均分给 3 个主节点不用手动cluster addslots。4. 装完必做的验证从集群状态到读写链路4.1 三层验证法状态、槽位、读写集群建完不能只看docker ps就完事我一般走三层验证。第一层看集群整体状态# 查看集群信息重点看 cluster_state 和 known_nodes docker exec -it redis-7001 redis-cli -a ${REDIS_PASS} cluster info # 查看节点列表确认 3 主 3 从、槽位分配完整 docker exec -it redis-7001 redis-cli -a ${REDIS_PASS} cluster nodescluster info里cluster_state:ok是底线如果显示fail说明有槽位没分配或节点失联cluster_slots_assigned:16384必须是 16384少一个都算不完整。cluster nodes输出里每个主节点后面跟的槽位区间要能拼成 0-16383 不重叠从节点状态是slave且connected。第二层验证槽位路由故意往不同 key 写数据看是否落到不同节点# -c 参数让 redis-cli 跟随重定向这是集群模式必须加的 docker exec -it redis-7001 redis-cli -c -a ${REDIS_PASS} set foo bar docker exec -it redis-7001 redis-cli -c -a ${REDIS_PASS} set hello world docker exec -it redis-7001 redis-cli -c -a ${REDIS_PASS} get foo-c是关键不加的话遇到MOVED重定向就报错。如果set foo返回MOVED xxxx 172.18.0.x:700x而没自动跳转说明-c漏了如果跳转后连接超时说明那个节点的端口映射有问题。第三层做故障转移演练手动停一个主节点看从节点是否顶上# 停掉 7001 主节点观察集群是否自动选主 docker stop redis-7001 sleep 10 docker exec -it redis-7002 redis-cli -a ${REDIS_PASS} cluster nodes | grep master正常情况下 10 秒左右原从节点会变成 mastercluster_state仍是 ok。验证完docker start redis-7001把它拉回来它会以从节点身份重新加入。这一层能过说明cluster-node-timeout和主从复制链路都是通的。4.2 一个容易被忽略的收尾习惯整套流程跑通后我有个雷打不动的习惯把docker ps、cluster info、cluster nodes三条输出存一份到/data/redis-cluster/baseline.txt。原因是有次集群跑了两周突然CLUSTERDOWN排查时根本想不起初始的节点 ID 和槽位分布只能推倒重建。有了基线文件对比一下就知道是哪个节点掉了、槽位怎么偏的。另外脚本里那个REDIS_PASS千万别用示例值上线我见过有人直接复制教程密码结果公网机器被扫到、数据被清空——集群密码和端口暴露这两件事装的时候多花五分钟比出事后再救省五天。希望这套流程帮到你少走我当年那些弯路。本文还有配套的精品资源点击获取