资讯详情

资讯详情

Docker Desktop下运行Redis:从安装配置到数据持久化的完整实践指南

1. 为什么我建议你在Docker Desktop里跑Redis先说结论如果你用的是Windows或者macOS想在本地开发环境里用上RedisDocker Desktop几乎是现阶段最省心的方案没有之一。为什么这么说Redis本身是个基于内存的键值存储系统官方虽然提供了Windows版本但一直停留在老版本而且安装、配置、启动服务这一套流程走下来会让你感觉回到了十年前。更麻烦的是你在Windows上装一个Redis跟线上Linux环境的行为总会有细微差异比如内存策略、文件系统行为、网络回环地址的处理方式这些差异平时不显眼一旦线上出问题就开始坑人。Docker Desktop的思路就简单多了——它本质上是在你的本机里跑了一个轻量级Linux虚拟机然后所有容器都跑在这个虚拟机里。你在Docker里装的Redis就是一个真正的Linux环境下的Redis跟线上服务器的行为几乎完全一致。这一点对于做后端开发的人来说价值巨大本地复现、联调、测试环境模拟全都建立在行为一致性这个基础上。另一个实际好处是隔离和清理。以前我在Windows上装原生Redis卸载的时候删注册表、删服务、清环境变量折腾半天还不一定能弄干净。用Docker之后一个docker rm -f命令就完事想换版本、换配置、起多个实例做集群模拟都是分钟级的事情。这篇内容适合哪些人刚接触Docker的初学者想在本地快速搭一个Redis环境的前端或全栈工程师以及被Windows版Redis坑过、准备切换到容器化方案的同学。我会把从零到能用的完整过程讲清楚包括镜像选择、数据持久化、配置文件挂载、连接测试这些核心环节最后再把我自己踩过的几个坑集中说一下。2. 动手之前的准备工作2.1 确认Docker Desktop本身状态正常这一步看起来多余但我在帮别人排查问题的时候至少有三分之一的情况是Docker Desktop本身就没跑起来。安装完Docker Desktop之后你先打开它等左下角的鲸鱼图标稳定下来不再是转圈状态。然后在终端里执行docker version正常情况下你会看到Client和Server两段信息Server段有内容说明Docker守护进程在正常运转。如果Server段报错或者直接没有先别急着继续重启Docker Desktop或者检查一下Windows的WSL2 / macOS的HyperKit虚拟化是不是被别的软件占用了。再跑一条docker ps这条命令会列出当前正在运行的容器。如果你是全新安装输出应该是空列表只有表头没有报错。这就说明Docker环境可以正常使用。2.2 关于镜像源的说明国内网络环境下直接拉取Docker官方仓库的镜像偶尔会很慢这算是基础问题但我不建议一上来就换各种第三方镜像源。因为第三方源经常有同步延迟、甚至中途停止服务的情况换源本身也是一件需要维护的事情。我的做法是先用默认源拉一次试试如果速度实在不行再考虑配置加速器。配置方法是打开Docker Desktop的Settings找到Docker Engine选项卡在JSON配置里加上registry-mirrors节点然后点击Apply Restart。这样改的只是拉取速度不影响镜像本身的安全性——当然如果你所在的环境对镜像来源有强约束请遵循你所在团队的规范。2.3 端口冲突检查Redis默认监听6379端口。如果你本机上已经有一个Redis在跑比如之前装过原生Windows版或者别的开发工具自带了Redis服务那Docker里的Redis容器启动时会因为端口被占用而报错。启动容器之前先确认一下6379端口的情况netstat -ano | findstr 6379Windows下如果看到有LISTENING的记录说明端口被占用了你就得在启动容器时换个宿主机端口比如6380后面的连接测试也相应地用6380。macOS下可以用lsof -i :6379来查。3. 镜像选择官方镜像就够了别整花活3.1 为什么推荐redis官方镜像而不是别人打包的Docker Hub上搜redis你会看到一大堆镜像什么bitnami/redis、redis-stack、各种带管理界面的全家桶。我个人的建议是需求不复杂的情况下直接选官方镜像redis。原因有三条。第一官方镜像的维护节奏跟Redis的版本发布是同步的。Redis出了新版本官方镜像几乎当天就更新。第三方镜像往往有滞后而且你没法确定维护者什么时候就不维护了。第二官方镜像的配置语义最标准。你之前在Linux上怎么用redis.conf在容器里就是怎么用不存在配置项被第三方镜像魔改的情况。第三官方镜像足够小基础镜像用的是Alpine Linux或者Debian的裁剪版体积小启动快攻击面也小。对一个本地开发环境来说这已经是最合适的平衡点。3.2 tag怎么选固定版本还是latest我的建议是本地学习或开发环境用latest没问题但如果你在一个稍微正式一点的环境里用请务必固定版本号。# 本地开发可以直接拉最新版 docker pull redis:latest # 或者拉一个明确的版本比如Redis 7.x docker pull redis:7.4-alpine7.4-alpine这种带alpine后缀的tag表示基于Alpine这个精简Linux发行版构建的镜像。Alpine版的优势是体积小通常比标准版小一半以上。缺点是它用的musl libc跟标准的glibc在一些边界行为上可能会有细微差异。Redis本身对这种差异不敏感所以对绝大多数场景没影响。固定版本号的价值在于可复现性。你今天拉的是7.4半年后别人再拉的时候如果用的是latest可能已经变成8.x了配置文件的行为可能有变化。版本固定下来环境才是可复现的踩到坑也知道去哪找答案。我自己早期就是偷懒用latest结果一次Redis大版本升级之后几个本来正常的命令行为变了排查了大半天才意识到是版本问题。4. 核心实操安装、配置、连接全流程4.1 最简安装先把Redis跑起来第一次尝试我不建议一上来就挂配置文件、做持久化目录映射因为如果出了问题你很难判断是Docker的问题还是配置的问题。先把最简单的跑通再一步步加东西。执行下面的命令docker run -d \ --name my-redis \ -p 6379:6379 \ redis:7.4-alpine逐条解释一下这几个参数因为理解了它们你后面才能灵活调整。docker run创建并启动一个新容器。-d后台运行容器起来了之后你的终端不会被它占住。不加这个参数Redis会直接在前台跑终端一关容器就停了。--name my-redis给这个容器起个名字。后续所有针对它的操作比如docker logs my-redis、docker stop my-redis都可以用这个名字来引用。我习惯给不同用途的容器起不同的名字比如redis-cache、redis-session方便区分。-p 6379:6379端口映射。左边是宿主机端口右边是容器内部端口。意思就是别人访问你本机的6379端口时数据会转发到容器内的6379端口。为什么需要这个因为容器默认是隔离的外面的程序直接访问不到它端口映射就是开一扇门。redis:7.4-alpine镜像名和tag。启动之后验证一下容器状态docker ps你应该能看到一个状态为Up的容器。然后测试连接docker exec -it my-redis redis-cli ping如果返回PONG说明Redis已经在容器里正常运行。docker exec的意思是进入一个正在运行的容器执行命令-it是交互模式redis-cli ping是Redis客户端发一个ping命令。这个PONG是Redis的经典回应见到它基本等于我活着而且能正常接收命令。4.2 用redis-cli做基本操作验证接着往里面写点东西试试docker exec -it my-redis redis-cli这会进入redis-cli的交互模式你可以敲set mykey hello get mykey正常会返回hello说明读写没问题。到这里一个最基本的Redis环境就算搭好了前后不过几分钟。不过我要提醒一句如果你用的是Windows的PowerShelldocker exec -it这条命令有时候会因为终端编码问题出现显示异常尤其是Redis返回中文内容的时候。解决办法有两个要么把终端切成Windows Terminal要么给redis-cli加一个--no-raw参数。这个问题不影响实际使用但是一旦遇到会让人莫名其妙提前知道可以少走弯路。4.3 数据持久化这步不做你一定会后悔Redis是一个内存数据库它默认是不把数据写到磁盘的。也就是说你往里面存了一堆数据Docker容器一删数据就全没了。有一个场景特别典型本地开发环境里你往Redis里存了一些测试用的业务数据比如Session、验证码、缓存的接口返回值。有一天你想升级Redis版本或者容器坏了需要重建手一滑把容器删了再重新启动一个发现里面空空如也——那种感觉我经历过真的不想再来一次。解决办法是挂载数据卷让Redis的数据落在宿主机磁盘上。修改启动命令docker run -d \ --name my-redis \ -p 6379:6379 \ -v redis-data:/data \ redis:7.4-alpine \ --appendonly yes这里的-v redis-data:/data是命名的数据卷映射。redis-data是卷的名字/data是容器内Redis存放持久化文件的目录。这个卷由Docker管理数据会存在Docker默认的数据目录里。你不需要关心它在宿主机上的具体路径Docker会帮你维护。好处是删除容器时数据还在再启动一个容器只要挂载同一个卷数据就回来了。后面那个--appendonly yes是Redis的启动参数意思是开启AOF持久化模式。Redis的持久化有两种方式RDB和AOF。RDB是每隔一段时间做一次全量快照优点是恢复快缺点是有可能丢失最近几分钟的数据。AOF是把每条写命令都追加到日志文件里最多丢配置策略内的少量数据恢复时通过重放命令来重建数据。对本地开发环境来说appendonly yes是个一劳永逸的设置。这里有个特别关键的坑要讲如果你选择匿名卷而不是命名卷比如写成-v /data那这个卷是跟容器绑定的容器删除之后匿名卷默认也会被清理掉。很多人以为我挂载了卷就万无一失了结果容器一删数据照样消失。要避免这个问题要么用命名卷像上面那样要么在删除容器时加-v参数去手动管理。4.4 配置文件挂载从默认配置到自定义配置如果你需要对Redis做比较细致的调优比如修改最大内存限制、设置密码、调整持久化策略那就要用到配置文件。Redis官方镜像支持通过挂载自定义配置文件的方式启动。步骤是这样的。先在宿主机上准备一个配置文件比如放在~/docker/redis/redis.confWindows用户可以用C:\docker\redis\redis.conf。文件内容里写你需要的配置项# 允许任意IP连接方便本地调试 bind 0.0.0.0 # 保护模式关掉本地测试不用那么严格 protected-mode no # 设置密码生产环境必须打开本地开发看情况 requirepass mysecret # 开启AOF持久化 appendonly yes然后挂载这个文件并指定Redis用它启动docker run -d \ --name my-redis \ -p 6379:6379 \ -v ~/docker/redis/redis.conf:/etc/redis/redis.conf \ -v redis-data:/data \ redis:7.4-alpine \ redis-server /etc/redis/redis.conf注意最后的redis-server /etc/redis/redis.conf。前面几个版本我们没写这部分Redis会用默认内置配置启动。现在写了它就会读取挂载进去的配置文件。这里有一个非常容易踩的坑配置文件里的权限和目录。容器内的Redis默认是以redis用户运行的如果你宿主机上配置文件权限设置不对比如Windows下从文件管理器里复制出来的文件带了一些奇怪的属性容器启动时会直接报Cant open the log file: Permission denied之类的错误。遇到这种情况先别怀疑配置内容检查一下文件权限和挂载路径。另一个坑是配置文件和redis-server的配合。如果你在docker run的最后不加那行redis-server /etc/redis/redis.conf而是只挂载了文件那么Redis依然会使用默认配置启动挂载的文件根本不会被读取。这个问题太常见了我看到过好几个人在社区里问为什么配置文件挂载了没生效基本都是这个原因。有密码之后连接方式也要变一下docker exec -it my-redis redis-cli -a mysecret ping或者先进入redis-cli再执行auth mysecret。注意命令行里直接-a传密码有个小隐患它可能会出现在进程列表里本地开发无所谓生产环境不要这么干。4.5 从宿主机程序连接容器内的RedisDocker容器默认的隔离性意味着你在宿主机上跑的一个Java程序、Node脚本、Python应用不能直接用localhost:6379去连接容器里的Redis——除非你做了-p 6379:6379端口映射。上面我们确实做了映射所以宿主机程序可以正常连接redis-cli -h 127.0.0.1 -p 6379 ping这里为什么要用127.0.0.1而不是localhost在大多数系统上两者等价但有些系统上localhost被解析成了IPv6的::1如果Docker的端口映射只绑定了IPv4就可能连不上。实测中这个问题的概率不高但遇到了会让人困惑。你可以在启动容器时加一个参数来绑定IPv4-p 127.0.0.1:6379:6379这样只监听回环地址的IPv4端口别人从局域网也访问不到你的Redis安全性更好。如果你只是本地开发自用我推荐都这么做。但是有一点特别重要如果你是在另一个容器里运行程序A想去连接这个Redis容器就不能用localhost了。因为每个容器是独立的网络命名空间localhost指向的是当前容器自己。正确的方式是创建一个自定义网络让两个容器都在这个网络里然后用容器名互相访问。docker network create dev-network docker run -d \ --name my-redis \ --network dev-network \ -p 6379:6379 \ redis:7.4-alpine docker run -d \ --name my-app \ --network dev-network \ my-app-image这样my-app容器里连接Redis时地址填my-redis端口填6379就能访问到。如果你不用自定义网络另一个容器想通过localhost连Redis容器在Windows和macOS的Docker Desktop环境下可以用特殊的主机名host.docker.internal它会被解析到宿主机。这个办法能用但只在Docker Desktop环境有效到了生产环境的Linux Docker上就不成立了。所以在容器间通信时正确的做法永远是自定义网络加容器名。5. 进阶主题连接可视化工具、版本升级与运维习惯5.1 装个RedisInsight比命令行直观一百倍命令行工具适合验证和脚本场景但如果你要分析Redis里的键分布、查看某个key的TTL、检查内存占用排行图形化工具要直观得多。Redis官方有一个可视化客户端叫RedisInsight支持Windows、macOS、Linux。跨平台这一点很重要因为你可能今天在Windows上开发明天切到macOS客户端数据和行为最好是一致的。RedisInsight连接容器里的Redis时需要注意鉴权配置。如果你在配置文件里设了requirepass mysecret在RedisInsight里新增连接时密码那一栏就填这个。如果没设密码RedisInsight默认会用redis-cli的方式连接可能能通但有些版本会因为保护模式拦截。最省事的做法是所有需要图形化连接的Redis都设一个密码即使是本地开发环境。另一个小技巧是RedisInsight可以配置SSH隧道如果你之后在远程服务器上跑Redis可以在不直接暴露6379端口的情况下安全连接。本地开发用不上这个但提前了解一下没坏处。5.2 升级Redis版本的正确姿势你在本地用一个Redis 6.x用了大半年现在想升级到7.x。如果你用的是原生安装这套流程会让你头大先备份数据、停服务、卸载、装新版、迁移数据、验证。用Docker就简单太多了而且数据不会丢——前提是你做了持久化挂载。第一步拉新版本的镜像docker pull redis:7.4-alpine第二步停掉旧容器但在删除之前确认数据已经持久化。只要你的数据在命名卷redis-data里删除容器不影响它。docker stop my-redis docker rm my-redis第三步用新镜像重新启动容器挂载同一个数据卷docker run -d \ --name my-redis \ -p 6379:6379 \ -v redis-data:/data \ redis:7.4-alpine \ --appendonly yes第四步验证数据docker exec -it my-redis redis-cli get mykey如果返回了之前的值说明迁移成功。整个过程五分钟内完成而且不需要导出导入数据因为Redis的数据文件格式在新版本里是兼容读取的。唯一需要注意的坑是Redis大版本升级时AOF文件的格式可能是向前兼容的但最好不要在第一次启动时就同时做升级版本和切换持久化模式两件事。先把版本升上来确认稳定再考虑要不要把RDB换成AOF或者反过来。一次只改变一个变量出问题了才知道问题出在哪。5.3 开发环境常用的运维命令集这里整理一份我平时用得最多的命令和场景方便你查阅。# 查看容器日志排查启动问题 docker logs my-redis # 实时跟踪日志输出 docker logs -f my-redis # 在容器里执行命令 docker exec -it my-redis redis-cli -a mysecret ping # 查看容器资源占用 docker stats my-redis # 停止容器保留容器和卷 docker stop my-redis # 启动已停止的容器 docker start my-redis # 删除容器不加 -v 不会删数据卷 docker rm my-redis # 删除容器并删除数据卷危险确认后再执行 docker rm -v my-redis # 查看所有数据卷 docker volume ls有一个场景值得单独说容器日志。Redis在启动时如果配置有误会打印错误信息然后退出。docker logs是你排查问题的第一手段。我见过有人把docker run -d改成docker run去掉-d让Redis在前台跑看着控制台输出排查问题这也行但没必要——用docker logs就够了而且不影响后台运行。5.4 资源限制一个容易被忽略的维度Docker Desktop默认会给你设置一个内存上限比如2GB或者4GB。Redis本身是单线程的内存数据库它占不了太多CPU但内存消耗需要关注。如果你在Redis里存了大量数据没设置maxmemory它就会一直吃内存直到容器能用的内存耗尽。更麻烦的是Docker Desktop有一个底层机制当某个容器内存占用超过限制时可能不会像Linux原生环境那样触发OOM而是表现出一系列奇怪行为比如连接超时、命令响应变慢。所以我的建议是在配置文件里设置一个合理的内存上限。maxmemory 256mb maxmemory-policy allkeys-lru第一行的意思是Redis最多用256MB内存超过之后按第二行的策略——allkeys-lru表示对所有键执行LRU淘汰也就是最近最少使用的键先被删掉。对本地开发来说这是一个比较合理的兜底策略。你不希望某个测试脚本往Redis里写了大量数据直接把内存吃爆吧。如果你用docker stats看到容器内存占用已经接近分配给Docker Desktop的额度优先排查是不是Redis或者其他容器的问题。6. 高频踩坑实录与排查手册6.1 容器启动后立刻退出状态是Exit这是最常见的问题。用docker ps -a看一下你会发现容器出现在列表里但状态是Exited (some code)。别慌按这个顺序排查。第一步看日志docker logs my-redis日志里最常见的报错是Cant open the config file /etc/redis/redis.conf: Permission denied这说明挂载的配置文件权限不对或者挂载路径写错了。用docker inspect看容器实际的挂载情况docker inspect my-redis | grep -A5 Mounts重点看Source和Destination是否是你预期的那一对。另一个常见报错是FATAL CONFIG FILE ERROR (Redis 7.x) Reading the configuration file, at line xx这说明配置项语法有问题对照你写的配置一行一行检查通常是缩进、注释符号、多余空格的问题。第二步确认端口映射。如果日志里出现bind: Address already in use说明宿主机6379被占用了按前面说的检查6219端口。6.2 WSL2模式下Redis数据丢失Windows用户如果用的是WSL2后端偶尔会遇到一种情况Docker Desktop还在运行但容器突然重启了然后数据丢了。这个问题的根源跟WSL2的虚拟磁盘生命周期有关而且Docker Desktop在升级、重启、或者Windows系统睡眠恢复时偶尔会触发WSL2虚拟机的重启。数据丢失的直接原因不是Docker的问题而是Redis持久化没有开启或者数据卷没有正确挂载。如果你用的是命名卷redis-data:/data即使容器重建数据也应该在。如果你只用了-v /data这种匿名卷容器重建或者Docker重置时卷可能就被删了。所以一定要用命名卷并且开启appendonly yes。这两点是开发环境数据安全的底裤缺一不可。另外Windows下的文件系统对性能有影响尤其是代码和配置直接放在Windows目录然后挂载给容器用的情况。如果Redis的RDB快照写入频繁而你把它放在Windows文件系统上性能可能明显下降。解决办法是配置文件这种小文件可以用Windows目录挂载但/data数据目录优先用命名卷让Docker把它放在WSL2内部文件系统里性能会好很多。6.3 localhost连不上但容器内部是通的有一些奇怪的场景是docker exec -it my-redis redis-cli ping能返回PONG但你在宿主机上用客户端连不上。先检查端口映射docker port my-redis正常输出应该是6379/tcp - 0.0.0.0:6379如果不是这个结果说明-p参数没生效。确认一下启动容器时的命令是否带了-p。如果端口映射正常再看Redis配置里的bind项。默认情况下配置文件里bind 127.0.0.1会限制Redis只监听容器内部的回环地址外部通过端口映射进来的流量会被拒绝。解决方法是像前面那样配置bind 0.0.0.0或者干脆不写bind行。注意这个bind是写在容器内Redis进程上的不是宿主机。6.4 Redis密码和建议的默认行为有些镜像或者一键脚本会在启动时自动给Redis设置密码比如Redis Stack镜像默认的密码可能是redis。如果你拉了一个镜像连接时始终显示NOAUTH Authentication required那就要考虑是不是镜像自带了密码。官方redis镜像默认是不设置密码的。如果你自己没在任何配置文件里写requirepass但连接时被要求认证那就检查一下容器启动命令里有没有别的参数注入。另外想多说一句Redis的protected-mode默认是yes这意味着即使没有密码Redis也会拒绝非回环地址的连接。本地开发时用127.0.0.1连接没问题但如果你想让局域网内的其他设备也能访问你的Redis就必须同时处理bind和protected-mode并且强烈建议设置密码。不设密码就把Redis暴露到局域网等于裸奔这个真不是危言耸听。6.5 Docker Desktop本身的问题导致Redis不可用有时候Redis容器一切正常但外部客户端就是连不上。这时候也别急着怀疑Redis先确认Docker Desktop本身的状态。Docker Desktop偶尔会出现端口转发失效的情况尤其是在Windows系统从睡眠中恢复、或者网络环境变化之后。症状是docker ps显示容器在运行docker exec也能执行但宿主机访问映射端口就是不通。最简单的办法是重启Docker Desktop。步骤是右键托盘图标选择Restart。等它完全起来之后再看docker ps通常端口转发就恢复了。如果重启Docker Desktop还不行重启电脑。这个问题的根源我到现在也没有特别确切的结论可能是Windows网络栈跟Docker的端口代理组件偶尔不同步。遇到就按上面的方法解决不用深究因为本质上这不是你配置的问题。7. 踩过这些坑之后我的一些体会最后说点实际的个人感受吧。用Docker Desktop跑Redis最大的好处其实是环境即代码的思维转变。以前装软件是装到系统里慢慢系统就变脏了、变乱了。现在用容器每一个中间件都是独立的、可替换的、可销毁的。这个思维转变的价值比学会几条docker命令大得多。第二个体会是Docker虽然方便但也抽象。你把Redis跑起来了问题排查的链路变长了。以前Redis连不上你只需要看Redis的日志现在你还要考虑容器网络、端口映射、Volume权限、Docker Desktop状态。所以我建议每一个用Docker的人至少把docker logs、docker ps -a、docker inspect这几个命令用熟这是你在容器世界里最基本的排查工具。最后再分享一个小技巧给容器起名字的时候别用Random后缀的默认名称也别用my-redis这种跟你实际用途完全无关的名字。我习惯用redis-项目名-用途这种格式比如redis-order-cache。用不了几秒钟但半年之后再看到这个容器你一眼就能知道它是干什么的。这个习惯在你一个机器上同时跑四五个Redis实例的时候会帮你省下大量时间。Docker Desktop装Redis这个事真的不难但里面值得注意的细节确实不少。如果你按照上面的步骤走一遍遇到问题也能对着排查手册找到答案整个过程应该不超过十分钟。后面再想折腾可以试着用Docker Compose把Redis跟你的应用服务一起编排起来那又是另一个话题了。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →