☰
Docker部署Redis实战:密码认证与数据持久化完整指南
2026/10/2 18:38:11 网站建设 项目流程

前阵子在云服务器上重新部署Redis,我把Docker部署Redis的全过程从头到尾捋了一遍,最核心的痛点还是那两个:密码访问和数据持久化。很多人第一次用Docker跑Redis,眼睛只盯着“docker run redis”这句话能出结果,结果容器一重启数据没了,或者6379端口直接裸奔在公网上被扫描器打爆。这篇文章就是来把这些事讲透的,面向的是要在服务器上真正落地Redis的朋友,不管你是第一次装,还是想系统梳理一遍完整部署姿势,都能直接照着做。

1. 先想清楚:为什么你需要的不是“把Redis跑起来”而是“一套部署方案”

拉镜像、跑容器、看到启动日志,这三步连起来也就一分钟。但生产环境里真正要命的问题全部发生在一分钟之后:容器删了数据还在不在?没有密码的Redis对公网开放意味着什么?参数堆在命令里下次还记不记得?

线上部署和本地开发最大的区别就是“可恢复性”。本地你用docker run redis跑一下,测试完删了无所谓的,Redis里那几条临时数据丢了也没人找你。但服务器上的Redis一旦承担缓存、session、分布式锁这些职责,你就要把它当成一个“有状态的长期服务”来部署,而不是一个“临时进程”。这个思维转换过来,后面每一步为什么这么做就都顺了。

1.1 镜像选型:不要上来就latest

我在服务器上部署时用的是redis:7-alpine,没有用redis:latest。原因有两点:

  • redis:latest虽然在持续更新,但你今天拉的和明天拉的可能不是同一个版本,环境可复现性差。生产部署应该锁定一个大版本,比如redis:7-alpine或更精确的redis:7.2-alpine。
  • alpine版本基于Alpine Linux构建,体积小,内存占用低,Redis本身是C语言写的,几乎不依赖glibc,跑在musl libc上完全没问题。服务器资源能省一点是一点。

如果你之后要用Redis模块或者特殊编译参数,那可能得考虑官方带编译工具链的镜像或者自己打镜像,但常规部署场景选redis:7-alpine就够了。

1.2 服务器上的Docker环境准备

很多朋友在本地用的是Docker Desktop,但服务器上装的是Docker Engine,这是两个东西。Docker Desktop是带图形界面的,适合开发机;服务器上一般直接用命令行操作Docker Engine。

装好之后先验一下环境:

docker version docker compose version

第一命令确认Docker Engine正常,第二个命令确认Compose插件可用。有些老机器上只装了docker-compose(带横杠、Python实现的旧版),新版是docker compose(不带横杠、Go实现的插件),两条命令的语法基本兼容,但优先建议用新版。这里先把基础打好,后面所有操作用到的就是docker和docker compose这两条命令。

2. 用一条命令先跑起来:密码和持久化参数逐个拆给你看

先把最简单的部署命令给出来,后面再逐步升级成生产可用的方案。先建目录,防止容器写入时因为目录不存在而出现权限或挂载异常:

mkdir -p /data/redis

然后运行容器:

docker run -d \ --name redis-server \ --restart unless-stopped \ -p 6379:6379 \ -v /data/redis:/data \ redis:7-alpine \ redis-server --requirepass "你的强密码" --appendonly yes

这条命令看着不长,但每个参数背后都有讲究,我一个个拆:

  • -d:后台运行容器,不然你的终端会一直卡在Redis日志输出上。
  • --name redis-server:给容器起个固定的名字,后面docker exec、docker logs、docker restart都靠它,别让Docker随机生成一个看不懂的名字。
  • --restart unless-stopped:服务器重启后容器能自动拉起来。unless-stopped比always更保守一点——如果你手动停下来,它不会在你意料之外强行启动,但机器重启时它会跟着起来。
  • -p 6379:6379:把容器内的6379端口映射到宿主机。这一步决定了外部能不能访问到Redis,后面安全组、防火墙的配置也是基于这个端口。
  • -v /data/redis:/data:把宿主机的/data/redis目录挂载为容器内的/data目录。Redis默认把RDB快照和AOF日志都写在/data下,你挂载了宿主机目录,这些文件就直接落在服务器磁盘上,容器删除后数据还在。
  • redis-server --requirepass "你的强密码" --appendonly yes:这段是在覆盖镜像默认的启动命令。官方Redis镜像默认就是启动redis-server,你在它后面追加参数,相当于告诉Redis服务“启动时开启密码认证、开启AOF持久化”。

跑起来之后,马上验证密码是不是真的生效了:

docker exec -it redis-server redis-cli -a 你的强密码 ping

输出:

PONG

如果不带密码试试:

docker exec -it redis-server redis-cli ping

你会看到:

NOAUTH Authentication required.

看到NOAUTH说明服务端已经设置了密码,只是你这次请求没有通过认证。这是正常的,而且是你想要的结果。

2.1 为什么网上说的REDIS_PASSWORD环境变量对你没用

这里要专门停下来提醒一个常见误区。网上有很多教程这么写:

docker run -d --name redis-server -e REDIS_PASSWORD=xxx redis

但实际上,官方Redis镜像的启动命令就是简单的redis-server,它不会去读取REDIS_PASSWORD这个环境变量。你加了这个-e参数,容器里虽然多了个环境变量,但Redis进程根本不看它,密码自然也就没有生效。

那为什么有人用着用着发现好像密码是生效的?因为他用的是第三方封装的镜像,或者他自己写了entrypoint脚本去处理这个变量。官方镜像不干这事。

如果你实在不想把密码直接写在docker run的命令行参数里(比如担心Shell历史记录、或者docker inspect能看到进程启动参数),可以改用Shell变量做一层间接传递:

docker run -d \ --name redis-server \ --restart unless-stopped \ -p 6379:6379 \ -v /data/redis:/data \ --env REDIS_PASSWORD='你的强密码' \ redis:7-alpine \ sh -c 'exec redis-server --requirepass "$REDIS_PASSWORD" --appendonly yes'

这种方式下,docker inspect redis-server看到的启动命令是sh -c 'exec redis-server --requirepass "$REDIS_PASSWORD"...',不会直接暴露明文密码。但注意,容器内的进程列表里最终还是会出现密码,这个方案只是减少了一部分暴露面,并不是万能保险箱。真正要做安全管理,用配置文件方式更清晰,下面一章展开。

3. 从“能跑”到“能上线”:用redis.conf管理密码与持久化

命令行参数的问题在于:参数一多就乱,也容易被忘。如果哪次重启容器时漏写了--requirepass,Redis又变回裸奔状态。所以线上真正落地的形态是——把配置沉淀到文件里。

3.1 准备一份最小可用的redis.conf

我习惯在宿主机上建这样一套目录结构:

/data/redis/ ├── config/ │ └── redis.conf └── data/

配置文件和数据文件分开,以后要改配置只需要动config/redis.conf,要备份数据只需要打包data/目录,互不干扰。

下面是常用的一份最小配置文件,你可以直接存为/data/redis/config/redis.conf:

bind 0.0.0.0 protected-mode yes port 6379 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no supervised no pidfile /var/run/redis_6379.pid loglevel notice logfile "" databases 16 always-show-logo no save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /data appendonly yes appendfilename "appendonly.aof" appendfsync everysec requirepass 你的强密码

几个关键项我展开说一下,后面排查问题都用得上:

  • bind 0.0.0.0:让Redis监听所有网卡。这步决定了外部网络能不能连上来。如果保持默认的127.0.0.1,那你只能在本机访问,外部工具永远连不上。0.0.0.0意味着暴露在网络上,所以一定要配合requirepass和安全组限制使用。
  • protected-mode yes:Redis的保护模式。它和requirepass是配合的关系——当你设置了密码,保护模式可以安全地保持开启;如果没设置密码又监听了所有网卡,Redis会拒绝外部访问。
  • appendonly yes:开启AOF持久化。这个决定了Redis在重启后能恢复到最新状态,而不是只靠RDB快照。
  • appendfsync everysec:每秒把AOF缓冲刷到磁盘。兼顾性能和数据安全。
  • dir /data:指定持久化文件的写入目录。镜像里Redis的工作目录本来就是/data,你挂载宿主机目录后,dump.rdb和appendonly.aof都会落在宿主机对应目录里。
  • requirepass:密码。

如果你不想手写配置,也可以从官方镜像里复制一份默认配置出来再改:

docker run --rm redis:7-alpine cat /usr/local/etc/redis/redis.conf > /data/redis/config/redis.conf

注意不同版本的镜像里配置文件路径可能略有差异,复制前可以用docker run --rm redis:7-alpine ls /usr/local/etc/redis/确认一下。

我自己更推荐手写上面那份精简配置。原因很简单:官方默认配置几百行,大部分注释对新手反而是噪音,还容易改错一个选项造成启动失败。精简配置只保留最核心的项,每行都知道它是干什么的,出了错也容易定位。

3.2 挂载配置并启动容器

配置文件准备好之后,重新创建容器:

docker rm -f redis-server docker run -d \ --name redis-server \ --restart unless-stopped \ -p 6379:6379 \ -v /data/redis/config/redis.conf:/usr/local/etc/redis/redis.conf \ -v /data/redis/data:/data \ redis:7-alpine \ redis-server /usr/local/etc/redis/redis.conf

注意最后一条命令:redis-server /usr/local/etc/redis/redis.conf。这会告诉Redis“别用默认配置,去读我挂载进去的这份文件”。挂载文件的好处是,容器外改配置、容器内立即生效(重启容器即可),完全不依赖命令行参数。

3.3 启动失败?多半是目录权限问题

如果你在这一步遇到容器反复重启,或者日志里出现:

Can't open the append-only file: Permission denied

那几乎可以断定是宿主机挂载目录的属主不对。

原因在于:官方Redis镜像为了安全,默认用redis用户运行进程,这个用户在镜像里的UID是999。你挂载进来的宿主机目录如果属主是root且权限是755,容器内的redis用户没有写权限,自然没法在/data下创建AOF文件。

解决办法很简单,在宿主机上执行:

chown -R 999:999 /data/redis

这里直接用数字999,不需要在宿主机上真的创建一个UID为999的用户,chown命令就是修改文件系统记录的属主ID,和系统里有没有这个用户名没关系。改完再重启容器:

docker restart redis-server

这个权限问题几乎每个人都会遇到一次,属于典型的“文档不会专门写、但实战天天碰”的坑。保姆级教程就得把它点出来。

4. 数据持久化到底保住了什么:RDB、AOF与重启验证

很多人对“持久化”的理解就是“数据不会丢”,但Redis的持久化其实是两套机制配合的:RDB和AOF。

RDB是快照,Redis会在满足一定条件时把全量数据写成一个二进制文件dump.rdb。它的加载速度快、文件紧凑,适合做备份。缺点是快照之间的数据可能丢失,比如你设置的save 900 1是“900秒内有1次写入就生成快照”,如果服务器在快照生成前突然断电,这900秒内的数据就没了。

AOF是追加日志,Redis把每一条写命令追加到appendonly.aof文件里,恢复时重新执行一遍命令。配合appendfsync everysec,最多丢一秒的数据。它的缺点是文件比RDB大,恢复时要重放命令,相对慢一些。

生产环境的正解是两者同时开启:RDB负责快速加载和备份,AOF负责把数据丢失窗口压缩到一秒以内。上面那份配置里已经都配好了。

4.1 重启一次看数据还在不在

配置完成后,做一次最直观的验证。往Redis里写一条数据:

docker exec -it redis-server redis-cli -a 你的强密码

进去后执行:

set attack_key "do not lose me"

然后退出容器,重启容器:

docker exec -it redis-server redis-cli -a 你的强密码 shutdown docker start redis-server

再进去查:

docker exec -it redis-server redis-cli -a 你的强密码 get attack_key

正常会返回:

"do not lose me"

这一步验证的是“容器重启后数据不丢”。更极端一点,你还可以验证“容器整个删除重建后数据也不丢”:

docker stop redis-server docker rm redis-server

然后用第3.2节那条docker run命令原样把容器建回来,再get attack_key,数据依然在。原因就是你挂载了/data/redis/data:/data,持久化文件在宿主机上,容器本身只是个“无状态外壳”。

4.2 备份与恢复的实际操作

持久化不等于备份,这点要拎清楚。持久化解决的是“进程重启不丢数据”,备份解决的是“磁盘坏了、误删了还能找回”。我习惯用这样一套备份动作:

mkdir -p /backup/redis docker exec redis-server redis-cli -a 你的强密码 BGSAVE cp /data/redis/data/dump.rdb /backup/redis/dump-$(date +%F).rdb cp /data/redis/data/appendonly.aof /backup/redis/appendonly-$(date +%F).aof

BGSAVE是让Redis在后台生成一份最新的RDB快照,生成完再复制文件,确保备份的是最新状态。

恢复则反过来:把备份的dump.rdb或appendonly.aof放回/data/redis/data/目录,改成对应的文件名,再执行:

chown -R 999:999 /data/redis/data docker restart redis-server

这里有个容易翻车的细节:Redis启动时如果同时发现了dump.rdb和appendonly.aof,默认会优先加载AOF文件。所以如果你从旧备份只恢复了RDB,但data/目录里还残留着一份更早的AOF文件,那Redis加载的可能不是你以为的那份数据。恢复时要么把文件放干净、要么干脆把data/目录整个清空后只放你要恢复的那一份,避免混着用。

5. 连接验证:命令行、可视化工具和安全组

部署完了,肯定要连上去看一眼。连接验证分几个层面,我逐个说。

5.1 服务器本机验证

在宿主机上执行:

docker exec -it redis-server redis-cli -a 你的强密码 ping

返回PONG,说明容器内部的服务和认证都正常。这一步只能证明Redis进程活着,不能证明端口映射正确。

5.2 外部工具连接

我最常用的图形化工具是Another Redis Desktop Manager(轻量、跨平台、免费)和Redis Desktop Manager。两者连接参数基本一样:

  • 地址:你的云服务器公网IP
  • 端口:6379
  • 密码:就是requirepass设置的那个

如果是在本地电脑上跑工具,连不上一般就两个原因:一是云服务商的安全组没放行6379端口,二是服务器系统防火墙没放行。

阿里云、腾讯云、华为云这些平台,除了服务器自己的防火墙规则,还有一个“安全组”层级的管控也必须配置。两个地方都要放行。

Linux服务器通常还开着ufw或firewalld。以ufw为例,最小授权方式是只放行你的办公IP:

ufw allow from 你的办公公网IP to any port 6379 proto tcp

而不是简单粗暴地ufw allow 6379,后者会让整个互联网都能扫到你的Redis端口。

5.3 常见连接失败排查表

现象原因解决办法
NOAUTH Authentication required.服务端已设置密码,请求未通过认证连接时填上密码
Connection refused端口没映射或者服务没起来docker ps看容器状态,确认-p 6379:6379
连接超时安全组或防火墙拦截检查安全组入方向、ufw status、iptables -L
Denied Redis protected-modeRedis没设密码但允许了外部访问设置requirepass,或把protected-mode yes保持开启

这个表基本覆盖了我帮别人排查问题时报错的前五名,按表格从上往下排查,大概率能定位。

6. 用Docker Compose把部署参数固化下来

docker run命令写一次还好,写两次、三次,你一定会怀念“一份文件搞定部署”的感觉。Docker Compose就是干这个的,把镜像、端口、数据卷、启动命令全部写进一个YAML文件里,版本化管理,换机器重新部署也就一条命令的事。

在/data/redis/目录下新建docker-compose.yml:

services: redis: image: redis:7-alpine container_name: redis-server restart: unless-stopped ports: - "6379:6379" volumes: - /data/redis/config/redis.conf:/usr/local/etc/redis/redis.conf - /data/redis/data:/data command: ["redis-server", "/usr/local/etc/redis/redis.conf"]

简单解释一下这个文件的映射关系:

  • image: redis:7-alpine:镜像来源。
  • restart: unless-stopped:开机自启策略,和docker run里的--restart一致。
  • ports:端口映射,注意YAML里的字符串写法"6379:6379",不加引号有些解析器会当成数字处理。
  • volumes:两个挂载,一个是配置文件,一个是数据目录。
  • command:覆盖默认启动命令,加载我们挂载进去的配置。

启动和日常操作命令汇总:

docker compose up -d # 启动/重建容器 docker compose ps # 查看容器状态 docker compose logs -f redis # 跟踪日志 docker compose restart redis # 重启服务 docker compose exec redis redis-cli -a 你的强密码 ping # 进容器执行命令 docker compose down # 停止并删除容器(注意:不会删宿主机的挂载目录)

用Compose之后,容器删除和重建变得非常“廉价”——因为配置和数据都在宿主机上,docker compose down再docker compose up -d,几秒钟就起来了,数据一点不少。

有个警告必须写清楚:执行docker compose down -v时,Compose会把声明为volumes的命名卷一并删除。上面那个文件里用的全是宿主机路径挂载(bind mount),所以即使带-v也不会删掉宿主机目录里的数据。但如果你哪天改用命名卷了,down -v就是真正的“粉碎性删除”,手滑一次数据全没了。所以我的习惯是:线上环境一律用宿主机路径挂载,备份、恢复都直观,Compose操作也更安全。

7. 线上运维的几个小提醒

部署完成只是开始,Redis跑在服务器上之后,还有几件事值得花几分钟做掉。

7.1 看日志

容器日志查看方式:

docker logs -f redis-server

Redis的启动信息、AOF文件报错、客户端连接断开等信息都会打在这里。之前提到的Permission denied就是从这个日志里看到的。

7.2 限制容器日志大小

Docker默认不限制容器日志大小,长时间运行,日志文件可能膨胀到几个GB,占满磁盘分区。可以在/etc/docker/daemon.json里加一段:

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

然后重启Docker:

systemctl restart docker

注意这个配置是全局的,重启后新创建的容器默认都受它约束,老容器要重建后才会生效。

7.3 升级Redis版本要备份先行

Redis大版本升级前,先从配置文件里确认当前的dump.rdb和AOF文件格式与新版是否兼容。稳妥流程是:

docker exec redis-server redis-cli -a 你的强密码 BGSAVE cp -r /data/redis/data /backup/redis/before-upgrade-$(date +%F)

然后修改docker-compose.yml里的image版本,再执行:

docker compose pull docker compose up -d

升级后第一时间做“写读验证”:写一个测试key,重启容器,确认数据还在。

我自己的体会是,Redis部署这件事本身不难,难的是把“密码访问”和“数据持久化”这两件事从“好像设置了”变成“确定生效了”。每一次部署完,我都会用三个动作验收:第一,redis-cli不带密码时是否被NOAUTH拦掉;第二,写一个key,重启容器,查一下是否还在;第三,确认云服务商安全组只放行了自己的办公IP,而不是0.0.0.0/0。这三件事过了,心里才踏实。

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

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

立即咨询