☰
Docker部署Redis 7实战:从持久化、ACL到主从复制
2026/9/25 2:48:55 网站建设 项目流程

上周我把一套老环境的 Redis 从 5.x 升到 7.2,用的方式不是下载源码编译,也不是找运维要现成安装包,而是直接docker部署redis7。说实话,这个决定一开始还有同事质疑,觉得容器里跑数据库不靠谱。等我依次搞定持久化、ACL 和主从复制,再用一条命令复制出一个一模一样的实例时,质疑的声音基本就没了。

这篇文章就是我这次从零到一部署 Redis 7 的完整记录。从环境准备、单机启动,到配置文件挂载、主从编排,再到实际部署中那些文档里不会写明的坑,统统一条条说清楚。想快速把 Redis 7 跑起来的新手可以照着抄,已经在用 Docker 但被网络、权限、数据持久化折磨过的老手,也可以重点看看最后一章。

1. 为什么我选择用 Docker 跑 Redis 7 而不是直接装二进制

先聊动机。很多人一听"容器里跑数据库"就皱眉,觉得性能有损耗、数据不安全。我理解这种顾虑,但实际用下来,至少在日常开发和中小规模生产场景里,容器化带来的收益远远大于那点可以忽略不计的损耗。

1.1 Redis 7 到底更新了什么,值得你升级

我之所以从 5.x 直接跨到 7,不是没事找事。Redis 7 相比 6.x 和 5.x,有几个变化是实打实能感受到的:

  • ACL v2 更完善了:可以精细控制某个用户只能访问哪些 key、执行哪些命令。以前要靠requirepass一把锁管所有人,现在可以给不同业务线、不同环境分配独立账号。
  • Redis Functions:官方推荐用 Lua Functions 替代零散的 Lua 脚本管理,脚本注册、版本管理都方便很多。
  • Sharded Pub/Sub:在集群模式下,发布订阅消息可以按分片传播,不用再全网广播,对大规模集群挺关键。
  • 内存效率优化:listpack 紧凑编码在哈希、ZSet 等场景下更省内存,7.x 对内存的利用比老版本强不少。

另外,Redis 7 的自动故障转移、副本切换逻辑也更成熟。如果你的 Redis 还停留在 4.x、5.x,升级到 7 其实是件性价比很高的事,兼容性方面我测下来没什么大问题。

1.2 容器化带来的实际好处

说回部署方式。传统装 Redis 要经历:下载源码或安装包、解决依赖、编译或解压、改配置文件、写 systemd 服务、设开机自启。这套流程做一次还行,做三次以上就烦了,尤其是要在同一台机器上跑多个不同版本的 Redis 做测试时,简直是灾难。

用 Docker 之后,日常操作变成这样:

  • 一条命令启动:docker run -d --name redis7 redis:7,完事。
  • 一台机器跑多个实例:只要宿主机端口不冲突,容器随便开,互不干扰。
  • 升级版本:改一下镜像 tag,docker pull新镜像,重启容器即可。回滚更是简单,旧镜像还在,docker run又起来了。
  • 配置可版本化:把redis.conf放进 Git 仓库,新机器上拉下来挂载进容器,服务环境完全一致。

我这次迁移到新服务器,整个过程没有下载过一个安装包,就是拉镜像、挂配置、起容器,十分钟不到恢复了一个和原来几乎一样的 Redis 服务。这点传统部署方式真比不了。

1.3 哪些场景别盲目上容器

当然,容器不是万能的。根据我的经验,下面这几种情况更适合传统二进制部署:

  • 对极致网络性能有要求:比如已经做了内核参数调优、CPU 绑核、专用万兆网卡的场景,容器多一层的网络转发虽然损耗极小,但追求极致时依然会介意。
  • 团队完全没人懂容器排障:如果出了问题,连docker logs、docker inspect都没人会用,建议先补课再上容器,别赶鸭子上架。
  • 数据目录没做持久化:这是最大的雷。很多人docker run一把梭,容器一删数据全没了。后面第四章会专门讲持久化,但提前说一句:任何数据库容器,不挂数据卷等于耍流氓。

所以我的结论是:不是所有场景都适合容器化,但大多数现代应用项目,Docker + Redis 7 这个组合,又简单又可靠,值得尝试。

2. 环境准备:先把 Docker 弄利索再谈 Redis

我见过太多人一上来就docker run,结果容器没起几个,全卡在环境问题上。环境准备这块虽然基础,但值得认真过一遍,尤其是 Windows 和 macOS 用户,容易在虚拟化层面翻车。

2.1 Linux 服务器:Ubuntu/CentOS 的安装差异

Linux 服务器是最常规的部署环境,但不同发行版的安装方式差别不小。

Ubuntu/Debian 系其实不用折腾,官方源里就有:

sudo apt update sudo apt install -y docker.io sudo systemctl enable --now docker

CentOS/RHEL 系稍微麻烦点,需要用 Docker 官方源或者发行版自带模块:

sudo dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install -y docker-ce docker-ce-cli containerd.io sudo systemctl enable --now docker

装完之后,记得把当前用户加进 docker 组,不然每次都要sudo docker:

sudo usermod -aG docker $USER

这个命令执行完要重新登录一次终端才生效。我当时第一次加完组没重登,还在奇怪为什么还是提示 permission denied,这个坑后面兄弟们很可能还会踩。

验证环境是否就绪,跑一下:

docker --version docker run hello-world

hello-world能正常输出一段欢迎信息,说明 daemon 已经通了。

2.2 Windows/macOS:Docker Desktop 与 WSL2 的那些事

Windows 上大家基本都会装 Docker Desktop,但它默认依赖 WSL2 后端,而 WSL2 又依赖 Windows 的虚拟化平台功能。很多人装好 Docker Desktop 一启动就报错:

Docker Desktop failed to start because virtualization support is not detected.

这个报错我帮人排查过好几次,原因基本是这几种:

  1. BIOS 里没开虚拟化:重启进 BIOS,找 Intel VT-x 或 AMD-V,开启并保存退出。
  2. Windows 功能没开启:打开"控制面板 -> 程序 -> 启用或关闭 Windows 功能",勾选"适用于 Linux 的 Windows 子系统"和"虚拟机平台",重启系统。
  3. WSL2 内核没升级:在管理员 PowerShell 里执行wsl --install,然后按提示重启即可。

macOS 倒是省心,装 Docker Desktop 的时候按提示给权限就行,但同样要注意 Apple Silicon 芯片的机器要选osx-arm64版本,Intel 老款选osx-amd64。

可视化界面调整内存也很关键。Docker Desktop 默认只给 2GB 内存,如果机器配置够,建议分 4GB 以上给虚拟化后端,否则容器一多直接各种 OOM。

2.3 镜像加速与 Redis 镜像选型

拉镜像慢是很多人入门的第一个痛。国内环境直连 Docker Hub 经常超时,但这件事的解决方案很成熟:各大云厂商都提供容器镜像加速服务,申请一个专属加速地址,然后在/etc/docker/daemon.json里配置:

{ "registry-mirrors": ["你的专属加速地址"] }

配置完重启 Docker:

sudo systemctl restart docker

至于镜像选型,Redis 官方镜像有几个 tag 需要注意:

镜像 tag特点适用场景
redis:7官方主线版本,体积较大生产环境首选,稳定靠谱
redis:7-alpine基于 Alpine Linux,体积很小本地测试、追求最小镜像
redis:7.2.4固定补丁版本生产环境锁版本时使用
redis:7.2.4-alpine固定版本 Alpine兼具版本锁定和小体积需求

线上环境我建议用redis:7或锁定具体小版本的redis:7.2.4。Alpine 版虽然只有三四十兆,但它用的 musl libc 和标准 glibc 在某些极端场景下行为略有差异,没必要为了省那几十兆在生产环境给自己添堵。

3. 单机快速部署:先让 Redis 7 跑起来再说

基础打好了,接下来就是动手环节。这一章从最简启动命令讲起,逐步把部署参数加全,你跟着操作就能在几分钟内拥一个干净的 Redis 7 实例。

3.1 最简启动命令和验证方法

在已经装好 Docker 的机器上,最简单的部署命令就一条:

docker run -d \ --name redis7 \ -p 6379:6379 \ redis:7

这条命令的参数含义拆开讲一下:

  • -d:后台运行容器。
  • --name redis7:给容器起个名字,方便后续管理,不用记那一长串容器 ID。
  • -p 6379:6379:宿主机 6379 端口映射到容器 6379 端口,这样外部才能通过宿主机 IP 访问 Redis。
  • redis:7:指定镜像,如果本地没有会自动从远端拉取。

启动后先看容器状态:

docker ps

再直接测试 Redis 是否活着:

docker exec -it redis7 redis-cli ping

如果输出PONG,说明 Redis 进程已经正常跑起来了。

我习惯再顺手确认一下版本:

docker exec -it redis7 redis-server --version

这样能确保拉下来的镜像确实是 7.x,而不是默认拉到什么奇怪的历史版本。

3.2 为什么用端口映射而不是 host 网络

新手常常问:我用--network host不是更省事吗?直接共享宿主机网络,Redis 就监听在宿主机 6379 上,容器没有任何 NAT 开销。

对单机单实例来说,host 网络确实没问题。但只要你需要在同一台机器上跑第二个 Redis 实例,冲突就来了:两个容器都要监听宿主机 6379,必然打架。

而桥接网络配合端口映射,每个 Redis 实例只需要换一个宿主机端口,比如 6380 映射容器 6379,就能优雅共存:

docker run -d --name redis7-test -p 6380:6379 redis:7

这样容器内部始终是 6379,外部访问 6380 即可,隔离性更好。默认bridge网络的端口映射性能损耗非常小,日常场景完全感知不到,没必要为了那一点点的极致性能去冒冲突风险。

3.3 容器内默认配置为什么会导致外连失败

最简命令启动的 Redis 有一个隐藏问题:外部客户端经常连不上。很多人第一反应是去开防火墙,其实问题大概率出在 Redis 的bind和protected-mode配置上。

Redis 编译源码的默认配置是:

bind 127.0.0.1 -::1 protected-mode yes

bind 127.0.0.1意味着只有 Redis 自己所在的那个网络能访问,容器外面自然进不来。protected-mode yes更狠,在没有配置密码的情况下,只允许回环地址连接。

不同版本的官方镜像在这个地方行为还不完全一样,有的做了容器专用适配,有的保留源码默认值。这就导致很多人按网上的教程启动后,一会儿能连上,一会儿连不上,特别迷惑。

最稳妥的做法:不要依赖默认配置,启动时显式指定监听地址,比如加--bind 0.0.0.0。如果你同时配置了密码,protected-mode的影响也会被抵消掉:

docker run -d \ --name redis7 \ -p 6379:6379 \ redis:7 \ redis-server --bind 0.0.0.0 --appendonly yes

但说实话,命令参数一多就乱,而且不利于复用。我强烈建议用配置文件方式管理,这个在第四章详细展开。

3.4 用 Docker Compose 来整理启动参数

如果容器启动参数超过两行,我就不太用docker run了,而是写一个docker-compose.yml。Compose 的好处是:配置即文件,能版本管理,团队其他人 clone 下来直接docker compose up -d就能复现环境。

一个最基础的 Redis 7 编排文件长这样:

services: redis7: image: redis:7 container_name: redis7 restart: always ports: - "6379:6379" volumes: - redis7-data:/data command: redis-server /usr/local/etc/redis/redis.conf volumes: redis7-data:

启动命令:

docker compose up -d

注意我这里的command已经指定要加载一个配置文件,但这个配置还不在,下一步就得把配置文件准备好。这正是从"能跑"到"能用"的关键分水岭。

4. 从"能跑"到"能上线":持久化、密码与自定义配置

很多教程到这里就结束了,但是!如果你只执行了上面那步就直接上线,数据丢失、被人扫描爆破 Redis 就是分分钟的事。这一章是全文最实战的部分,请务必看完。

4.1 先解决数据不丢的问题:数据卷与持久化

先说一个让人冷汗直流的场景:

docker rm -f redis7 docker run -d --name redis7 -p 6379:6379 redis:7

两条命令下去,容器是新的了,但 Redis 里的所有数据也都没了。这就是没有挂载数据卷的后果——容器是沙箱,删除容器时默认把容器内的可写层也一起删了。

Redis 官方镜像本身就是把数据目录指向/data的,所以我们只需要把容器的/data目录挂载到宿主机的一个目录或命名卷上即可:

docker run -d \ --name redis7 \ -p 6379:6379 \ -v redis7-data:/data \ redis:7

这样数据会写在 Docker 命名卷redis7-data里,容器删除重建后,数据仍在。

上述只是目录挂载,更关键的是 Redis 自身的持久化策略。Redis 提供两种持久化机制:

  • RDB(快照):每隔一段时间把整个数据集打成快照存盘。优点恢复速度快、文件紧凑,缺点两次快照之间的数据可能丢失。
  • AOF(追加文件):每执行一次写操作就追加一条记录到文件。优点数据丢失窗口小,缺点文件体积大、恢复速度慢。

Redis 7 的默认行为是 RDB 开启、AOF 关闭。如果你需要更可靠的数据保障,建议显式开启 AOF。AOF 里有三个刷盘策略,各有取舍:

配置项行为数据安全性性能开销
appendfsync always每次写操作都同步到磁盘最高,基本不丢最大
appendfsync everysec每秒同步一次高,最多丢 1 秒数据适中
appendfsync no交给系统决定何时刷盘较低最小

我常用的组合是 RDB + AOF 同时开启,且 AOF 用everysec,既保证恢复速度,又控制数据丢失窗口。

4.2 密码认证:从 requirepass 到 ACL

Redis 默认没有密码,这就是裸奔。尤其是你把端口映射到公网之后,脚本扫描到就在那儿不断试探。我的经验是,Redis 一定要设密码,而且别用123456这种,很容易被打。

最简单的设置方式是在启动命令里加--requirepass:

docker run -d \ --name redis7 \ -p 6379:6379 \ -v redis7-data:/data \ redis:7 \ redis-server --requirepass '你的强密码'

这样连接时就要认证了:

redis-cli -h 127.0.0.1 -p 6379 -a '你的强密码'

或者连上后手动执行:

127.0.0.1:6379> AUTH '你的强密码' OK

不过requirepass是一把锁管所有人,Redis 7 更推荐的其实是 ACL。ACL 可以创建多个用户,每个用户有自己独立的密码,还能限制可访问的 key 范围和命令白名单。

我用 ACL 给不同业务线开账号的示例:

127.0.0.1:6379> ACL SETUSER user_business1 on >'独立密码' ~cache:* +@read +@write +@admin

这条命令创建了一个名为user_business1的用户,密码是"独立密码",只能操作cache:前缀的 key,并允许读、写和管理类命令。业务系统连接时用这个专属账号,权限边界很清楚,即使密码泄露,影响也是受限的。

配置文件里如果要写 ACL,可以这样:

user user_business1 on >'独立密码' ~cache:* +@read +@write +@admin

Redis 7 的 ACL 权限模型比老版本成熟太多,值得花点时间研究。

4.3 自定义 redis.conf:把所有参数集中管理

启动参数越堆越长时,我的选择是:写一份redis.conf,挂载进容器,启动时加载它。这样所有配置集中在一个文件里,可比性、可读性、可管理性全部提升。

我的一份常用 Redis 7 配置文件长这样,直接用:

bind 0.0.0.0 protected-mode yes port 6379 daemonize no dir /data # 持久化 appendonly yes appendfsync everysec save 900 1 save 300 10 save 60 10000 # 密码认证 requirepass '你的强密码' # 内存管理 maxmemory 512mb maxmemory-policy allkeys-lru # 日志 loglevel notice logfile ""

几个关键项说明一下:

  • bind 0.0.0.0:允许所有网络接口监听,配合密码使用才安全。
  • protected-mode yes:开启保护模式,没有配置密码时限制外部访问,双保险。
  • daemonize no:容器内必须以前台进程方式运行,否则容器会启动即退出。
  • dir /data:持久化文件写入/data,配合挂载目录才能落盘到宿主机。
  • maxmemory和maxmemory-policy:给 Redis 设置内存上限,避免内存无限增长拖垮宿主机。allkeys-lru是在内存满时按最近最少使用淘汰 key。

启动时加载这份配置:

docker run -d \ --name redis7 \ -p 6379:6379 \ -v redis7-data:/data \ -v $PWD/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7 \ redis-server /usr/local/etc/redis/redis.conf

这里我把配置文件和宿主机当前目录绑定,意味着以后改配置只需编辑宿主机上的redis.conf,然后重启容器:

docker restart redis7

对应的 Compose 文件也自然升级成:

services: redis7: image: redis:7 container_name: redis7 restart: always ports: - "6379:6379" volumes: - redis7-data:/data - $PWD/redis.conf:/usr/local/etc/redis/redis.conf command: redis-server /usr/local/etc/redis/redis.conf volumes: redis7-data:

这里提醒一个 Windows 上的坑:如果你用文本编辑器在 Windows 下编辑过redis.conf,文件换行符可能是 CRLF,Redis 解析配置时可能报错或行为异常。解决办法是把换行符改成 LF,或者直接用 VS Code 右下角切换行尾序列。

4.4 权限问题:别忽略挂载目录的属主

还有一个新手极容易踩的坑:配置文件挂载成功了,但 Redis 启动后无法写持久化文件,日志里报 permission denied。

原因是官方 Redis 镜像默认以redis用户运行,这个用户在容器内的 UID 通常是999。宿主机挂载进容器的目录如果属于 root 或其他用户,Redis 进程就没有写权限。

解决办法是把目录属主改成 999:

sudo chown -R 999:999 /path/to/redis-data

如果你用的是命名卷redis7-data,那 Docker 初始化时一般会自动处理权限,问题不大;但用宿主机绝对路径挂载目录时,这个chown几乎是必做的。我最初部署时就在这里卡了快一个小时,日志翻来覆去就看不出问题,后来ls -l一看目录属主才发现,全是血的教训。

5. 继续深入:主从复制、哨兵与集群

单机部署只是入门,线上真正要面对的是高可用。Redis 官方给出的路径是:主从复制 -> 哨兵 -> 集群。这里就把最常用的主从复制和进阶方案讲清楚。

5.1 从零搭建 Redis 主从复制

为什么需要主从复制?最直白的理由有三个:读多写少的场景可以分流读请求;从节点可以当热备;主节点挂了之后从节点能顶上。

Redis 主从复制的原理很简单:从节点连上主节点后,主节点把数据同步给从节点,后续的写操作也会实时同步。

在 Docker 里手动搭一主一从,可以这样操作。先启动主节点:

docker run -d \ --name redis-master \ -p 6379:6379 \ -v redis-master-data:/data \ redis:7 \ redis-server --appendonly yes --requirepass 'Master密码'

再启动从节点,关键参数是--replicaof,指定主节点的宿主机 IP 和端口:

docker run -d \ --name redis-slave \ -p 6380:6379 \ -v redis-slave-data:/data \ redis:7 \ redis-server --replicaof 宿主机IP 6379 --masterauth 'Master密码' --requirepass '从节点密码'

注意从节点必须通过--masterauth提供主节点的密码,不然复制握手都会失败。

验证主从是否生效,进入从节点执行:

docker exec -it redis-slave redis-cli -a '从节点密码' info replication

重点关注这段输出:

role:slave master_host:宿主机IP master_port:6379 master_link_status:up

只要master_link_status:up,就说明复制链路正常。接着在主节点写一个 key,在从节点马上能读到,同步成功。

5.2 用 Compose 编排一主二从:顺带解决容器互访

手动docker run搭多个节点时,容器之间网络互通是个麻烦事。尤其从节点连主节点时,如果用宿主机 IP,本地防火墙可能拦;用容器 IP,那边容器一重建 IP 就变了,全是坑。

Compose 里这些问题会优雅很多:Compose 会默认创建一个项目网络,services之间可以直接用服务名互相访问,比如redis-master:6379。

一个一主二从的 Compose 编排长这样:

services: redis-master: image: redis:7 container_name: redis-master restart: always ports: - "6379:6379" volumes: - redis-master-data:/data command: redis-server /usr/local/etc/redis/redis.conf redis-slave1: image: redis:7 container_name: redis-slave1 restart: always ports: - "6380:6379" volumes: - redis-slave1-data:/data command: redis-server /usr/local/etc/redis/redis.conf redis-slave2: image: redis:7 container_name: redis-slave2 restart: always ports: - "6381:6379" volumes: - redis-slave2-data:/data command: redis-server /usr/local/etc/redis/redis.conf volumes: redis-master-data: redis-slave1-data: redis-slave2-data:

然后每个从节点的redis.conf里写上:

replicaof redis-master 6379 masterauth Master密码 requirepass 从节点密码

使用 Compose 之后,节点间通信走服务名解析,不再依赖宿主机 IP,容器重建也不怕 IP 变化,这才是容器编排该有的样子。

5.3 Sentinel 还是 Cluster:怎么选更合适

主从复制只能解决读流量分担和手动切换,主节点真正挂了,不可能指望人半夜爬起来手动改配置。再往上一层的两个方向是 Sentinel 和 Cluster。

Sentinel(哨兵):本质上是监控进程,监控一个主节点和若干从节点。主节点挂掉时,Sentinel 自动把某个从节点提升为新主节点,业务侧通过 Sentinel 获取当前主节点地址,实现了自动故障转移。哨兵模式适合数据量不大、单体 Redis 够用但要高可用的场景。

Cluster(集群):数据分片存储,把数据按哈希槽分散到多个主节点上,每个主节点又有自己的从节点。集群模式适合数据量大到单机装不下、写并发也高的场景,但部署要至少 6 个节点(3 主 3 从),复杂度比哨兵高不少。

Docker 里手动部署 Cluster 不是不行,但要在每个节点上设置cluster-enabled yes、cluster-announce-ip这些参数,节点还得能互相发现,编排文件会非常长。我的建议是:如果你的业务确实需要 Redis Cluster,第一选择是用云厂商的托管集群版或 Kubernetes 上的 Redis Operator,不建议自己拿裸容器硬撸集群,成本和风险都很高。

主从 + 哨兵是自建 Redis 高可用的性价比之选,这个方向值得花时间研究透。

6. 实战中的高频坑与排查思路

最后一章,把我这一年多使用 Docker 部署 Redis 遇到的各种疑难杂症集中盘点一遍。这些问题有些很冷门,但遇到了真的很折磨人,希望看完能帮你省下几个小时的排查时间。

6.1 外部连不上 Redis:先别急着开防火墙

业务系统连 Redis 超时或拒绝连接,是出现频次最高的问题。很多人第一反应就是去改防火墙、开端口,但十有八九白忙活。

我总结了一套排查链路,按顺序走基本能找到根因:

  1. 看端口映射:docker ps看宿主机端口是否映射成功。如果端口没映射出来,外部自然连不上,问题出在-p参数。
  2. 看容器日志:docker logs redis7,如果有报错直接处理,比如配置语法错误、文件权限问题都在这里现形。
  3. 进容器看监听地址:docker exec -it redis7 redis-cli config get bind,如果返回127.0.0.1,立刻知道问题就是 Redis 只监听了回环地址,外部请求根本进不来。
  4. 检查保护模式:docker exec -it redis7 redis-cli config get protected-mode,如果既是no密码又是yes保护模式,也会拒绝外部连接。

确认是bind问题后,按第四章那段配置改成bind 0.0.0.0,重启容器,基本就通了。不要在没确认 Redis 自身配置前就急着动防火墙,这是排查顺序的关键。

6.2 Docker Desktop 启动失败与 WSL2 网络不灵

前面提到过virtualization support not detected,这里再补充一个高频报错:

Failed to connect to the docker API at npipe:////./pipe/dockerDesktopLinuxEngine...

这个报错出现在 Windows 上,本质是 Docker Desktop 的 Linux 后端没起来,常见原因和对应的解决办法:

现象可能原因解决办法
启动报 npipe 连接失败Docker Desktop 服务没完全启动右键托盘图标选 Restart,等待一分钟
WSL2 子系统状态异常WSL 内核卡死PowerShell 里执行wsl --shutdown再重开
虚拟机平台功能缺失Windows 功能未开启"启用或关闭 Windows 功能"里勾选虚拟机平台,重启系统
一直转圈起不来Docker 数据损坏尝试 Reset Docker Desktop 的 WSL 数据(会丢容器数据,慎用)

WSL2 模式下,如果容器网络不通,我还会检查 Windows 防火墙是不是拦截了 WSL 虚拟网卡的流量。总之在 Windows 上玩 Docker,先把 WSL2 的底子打好,后面才顺。

6.3 容器重启后 IP 变了导致业务连不上

这个坑特别隐蔽。很多人在同一个 Docker 网络里部署了多个容器,然后在业务配置里直接填了某个容器的 IP(比如docker inspect查出来的 172.17.0.x),结果一重启容器,IP 变了,业务瞬间全断。

容器 IP 本来就是动态分配的,eth0 的地址每次创建都可能变化。正确做法有两种:

  1. 使用端口映射:业务访问宿主机 IP + 映射端口,不关心容器内部 IP。
  2. 使用 Docker 网络的服务名解析:在同一个自定义 Docker 网络内的容器,直接互相用容器名访问,比如 Compose 里的redis-master:6379。Docker 内置 DNS 会解析到正确地址,容器重建后 IP 变了也能自动跟上。

我之前见有人把所有容器网络都落在默认bridge上,然后互相用 IP 访问,结果运维一个不小心重启了几个容器,整个服务调用链直接崩掉。这种问题排查起来特别磨人,因为表面上看容器都活着。

6.4 镜像下载慢或拉取超时

这几乎是国内开发者绕不过去的问题。拉 Redis 官方镜像偶尔卡半天,我还见过docker pull直接超时失败的。

解决办法前面提过:配置镜像加速器。在/etc/docker/daemon.json中添加加速地址,重启 Docker 后生效。需要注意加速服务通常需要你自己申请,云厂商都提供了免费的个人专属加速地址,申请完填进去即可。

另外一个小经验:docker pull时如果某个层卡住,可以先 CTRL+C 取消,再重新执行docker pull,很多情况下会从断点继续而不是重新下载,比干等靠谱。

如果已经配置了加速还是很慢,可以检查一下是不是使用了多架构 manifest:比如在 x86 机器上拉取一个同时包含amd64和arm64的镜像,客户端会自动选择对应架构,但也可能因为网络原因拉取失败。实在不行,可以显式指定平台:

docker pull --platform linux/amd64 redis:7

6.5 容器日志和内存膨胀问题

Redis 容器跑久了,日志可能越来越大,内存也可能被吃满。这里分享两个我常用的边界控制手段。

日志方面,容器默认的所有 stdout 都会进json-file日志文件,如果不限制,一个日志刷得猛的容器能把宿主机的磁盘写爆。建议在daemon.json里统一设置日志轮转:

{ "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" } }

配置后重启 Docker 生效。这个配置对 Redis 这种日志不算多的应用可能问题不大,但如果你在同一台机器上还跑了其他服务,统一设置总没错。

内存方面,Docker 层面可以用--memory限制容器能使用的内存上限,Redis 层面则用maxmemory配置上限。两层的含义不同:--memory是容器层的硬限制,超了会 OOM;maxmemory是 Redis 自己的限制,超了会触发淘汰策略。建议两者都设置,且maxmemory要略小于容器内存限制。比如容器限制 1GB,Redis 的maxmemory就设 800MB,留出系统自身的缓冲和碎片内存。

最后再说两句

写了这么多,其实都是这一个多月来回折腾攒下的经验。如果你目前还在纠结要不要用 Docker 部署 Redis 7,我的态度很明确:在已经把持久化和密码处理好、配置能版本化的前提下,直接上,没有想象中那么玄乎。

我自己的习惯是,每套环境都先把redis.conf和docker-compose.yml准备好再执行docker compose up -d,不做那种命令一敲完就走的事。提前把数据卷、端口、资源限制都想清楚,后续运维会省心很多。

这套流程现在已经在我手头几个项目里稳定跑着,希望对你有帮助。如果你在部署中遇到其他奇怪的问题,也可以照着上面的排查思路先把docker logs、docker exec、docker inspect三件套用起来,很多问题自己就能定位。

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

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

立即咨询