Redis的dev环境docker搭建
1、前言
本文主要针对M2下,相应进行开发环境搭建,然后做一个文档记录,是第二弹文章,搭建是采用docker compose文件。
希望对相关人有帮助。如果只想要Docker-Compose文件,请转到第三节的单机模式和第四节的集群模式。
原本是打算使用redis-commander进行docker集群内访问redis cluster,但是很可惜,官方似乎在docker compose组建的运行环境下是存在问题的,Issue看这。
2、官方文档重点信息提取
redis的docker镜像官网地址在此处点击。
2.1、创建redis实例
docker run --name some-redis -d redis
如果想持久化,则是如下命令:
docker run --name some-redis -d redis redis-server --save 60 1 --loglevel warning
redis-server --save 60 1 --loglevel warning
,这是传递给 Redis 服务器的参数,它告诉 Redis 服务器在后台每隔 60 秒检查一次数据库,如果有至少一个键被修改,则将其写入磁盘。后面的 1 表示如果至少有一个键被修改,则每秒进行一次检查。–loglevel warning 设置 Redis 服务器的日志级别为 “warning”,表示只记录警告级别的日志。
2.2、使用自己的redis.conf文件。
创建自己的Dockerfile文件,将上下文中的redis.conf添加到/data/中,如下所示
FROM redis
COPY redis.conf /usr/local/etc/redis/redis.conf
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
也可以使用docker命令
docker run -v /myredis/conf:/usr/local/etc/redis --name myredis redis redis-server /usr/local/etc/redis/redis.conf
其中/myredis/conf/是包含redis.conf文件的本地目录。使用这种方法意味着你不需要为你的redis容器创建Dockerfile。
映射的目录应该是可写的,因为根据配置和操作模式,Redis可能需要创建额外的配置文件或重写现有的配置文件。
3、单机版redis搭建
先创建redis单机版的目录。
mkdir redis-single
然后在redis-single目录下,创建两个目录,一个是conf,一个是data
mkdir conf data
在conf目录下创建redis.conf文件
# redis-single.conf
# 允许来自任何IP的连接
bind 0.0.0.0
# 设置启动保护模式
# protected-mode yes
# 设置密码
requirepass test123
save 900 1 # 在900秒(15分钟)内,如果至少有1个键被修改,就创建一个RDB快照
save 300 10 # 在300秒(5分钟)内,如果至少有10个键被修改,就创建一个RDB快照
save 60 10000 # 在60秒内,如果至少有10000个键被修改,就创建一个RDB快照
appendonly yes # 启用了 AOF 持久化
appendfsync everysec # 将写操作追加到AOF文件并在每秒同步一次
上述配置为aof持久化的时机,解释如下:
然后回退到上一级目录,即redis-single目录下,创建docker-compose.yml文件,文件内容如下所示:
version: '3.1'
services:
redis-single:
image: redis:latest
restart: always
ports:
- "6379:6379"
volumes:
- /Users/tanqiwei/docker-dev/redis-single/data:/data
- /Users/tanqiwei/docker-dev/redis-single/conf/redis-single.conf:/etc/redis/redis.conf
command: ["redis-server", "/etc/redis/redis.conf"]
然后输入下面命令启动:
docker compose up
然后外部用一些redis的可视化客户端连接进行连接,然后进行key的创建和更新都是正常的。
4、redis集群版
redis集群版,最开始写的很顺利,而且成功运行,但是目前为止,我依旧没找到任何可以通过外部手段连接该集群的方式,等待后续更新,集群是正常创建的。
由于使用redis cluster,创建3节点主,3节点副本,所以一共是6个节点。
首先创建redis-cluster目录
mkdir redis-cluster
同样是在这个目录下,创建conf data两个文件夹。
mkdir conf data
然后进入conf目录,创建redis-master.conf文件,内容如下:
# redis-cluster.conf
# 启用集群模式
bind 0.0.0.0
cluster-enabled yes
cluster-node-timeout 5000
requirepass test123
cluster-config-file nodes.conf
masterauth test123
# 在900秒(15分钟)内,如果至少有1个键被修改,就创建一个RDB快照
save 900 1
# 在300秒(5分钟)内,如果至少有10个键被修改,就创建一个RDB快照
save 300 10
# 在60秒内,如果至少有10000个键被修改,就创建一个RDB快照
save 60 10000
# 启用了 AOF 持久化
appendonly yes
# 将写操作追加到AOF文件并在每秒同步一次
appendfsync everysec
然后使用cp命令创建另外5个文件(文件内容一模一样)。
tanqiwei@tanqiweideMacBook-Pro conf % ls
redis-master.conf redis-node2.conf redis-slave1.conf
redis-node1.conf redis-node3.conf redis-slave2.conf
然后回到上一层下的data目录,分别创建如下六个文件夹(文件夹名分别为master、node1、node2、node3、slave1、slave2):
tanqiwei@tanqiweideMacBook-Pro data % ls
master node1 node2 node3 slave1 slave2
接着回到redis cluster,创建下面的docker-compose文件。
version: '3.1'
services:
redis-cluster:
image: 'redis:latest'
entrypoint: /bin/sh -c
command: >
"echo yes | redis-cli --cluster create
198.20.0.31:6379
198.20.0.32:6379
198.20.0.33:6379
198.20.0.34:6379
198.20.0.35:6379
198.20.0.36:6379
--cluster-replicas 1 --pass test123"
networks:
redis_cluster_subnet:
ipv4_address: 198.20.0.30
depends_on:
- redis-master
- redis-slave1
- redis-slave2
- redis-node1
- redis-node2
- redis-node3
redis-master:
image: redis:latest
restart: always
ports:
- "7001:6379"
volumes:
- /Users/tanqiwei/docker-dev/redis-cluster/data/master:/data
- /Users/tanqiwei/docker-dev/redis-cluster/conf/redis-master.conf:/etc/redis/redis.conf
command: ["redis-server", "/etc/redis/redis.conf"]
networks:
redis_cluster_subnet:
ipv4_address: 198.20.0.31
redis-slave1:
image: redis:latest
restart: always
ports:
- "7002:6379"
volumes:
- /Users/tanqiwei/docker-dev/redis-cluster/data/slave1:/data
- /Users/tanqiwei/docker-dev/redis-cluster/conf/redis-slave1.conf:/etc/redis/redis.conf
command: ["redis-server", "/etc/redis/redis.conf"]
networks:
redis_cluster_subnet:
ipv4_address: 198.20.0.32
redis-slave2:
image: redis:latest
restart: always
ports:
- "7003:6379"
volumes:
- /Users/tanqiwei/docker-dev/redis-cluster/data/slave2:/data
- /Users/tanqiwei/docker-dev/redis-cluster/conf/redis-slave2.conf:/etc/redis/redis.conf
command: ["redis-server", "/etc/redis/redis.conf"]
networks:
redis_cluster_subnet:
ipv4_address: 198.20.0.33
redis-node1:
image: redis:latest
restart: always
ports:
- "7004:6379"
volumes:
- /Users/tanqiwei/docker-dev/redis-cluster/data/node1:/data
- /Users/tanqiwei/docker-dev/redis-cluster/conf/redis-node1.conf:/etc/redis/redis.conf
command: ["redis-server", "/etc/redis/redis.conf"]
networks:
redis_cluster_subnet:
ipv4_address: 198.20.0.34
redis-node2:
image: redis:latest
restart: always
ports:
- "7005:6379"
volumes:
- /Users/tanqiwei/docker-dev/redis-cluster/data/node2:/data
- /Users/tanqiwei/docker-dev/redis-cluster/conf/redis-node2.conf:/etc/redis/redis.conf
command: ["redis-server", "/etc/redis/redis.conf"]
networks:
redis_cluster_subnet:
ipv4_address: 198.20.0.35
redis-node3:
image: redis:latest
restart: always
ports:
- "7006:6379"
volumes:
- /Users/tanqiwei/docker-dev/redis-cluster/data/node3:/data
- /Users/tanqiwei/docker-dev/redis-cluster/conf/redis-node3.conf:/etc/redis/redis.conf
command: ["redis-server", "/etc/redis/redis.conf"]
networks:
redis_cluster_subnet:
ipv4_address: 198.20.0.36
networks:
redis_cluster_subnet:
driver: bridge
ipam:
config:
- subnet: 198.20.0.0/24
在这个docker compose文件里面,为了能6个节点互联,且能够固定IP,所以我采用了子网的方式。
networks:
redis_cluster_subnet:
driver: bridge
ipam:
config:
- subnet: 198.20.0.0/24
然后每个redis集群,其实按照单机版的方式处理,只是加了网络的选项,而且配置文件设置了以集群方式开启。
最后定义了一个名为 redis-cluster 的服务,使用最新版本的 Redis 镜像。entrypoint 和 command 部分包含了在容器启动时执行的命令,用于初始化 Redis 集群。
然后执行docker compose up的命令就能启动成功。
4.1、一些验证
docker exec -it redis-cluster-redis-master-1 /usr/local/bin/redis-cli -c -a test123 --cluster check 198.20.0.31:6379
输出如下所示:
tanqiwei@tanqiweideMacBook-Pro data % docker exec -it redis-cluster-redis-master-1 /usr/local/bin/redis-cli -c -a test123 --cluster check 198.20.0.31:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
198.20.0.31:6379 (b244b72f...) -> 0 keys | 5461 slots | 1 slaves.
198.20.0.33:6379 (183e2e42...) -> 0 keys | 5461 slots | 1 slaves.
198.20.0.32:6379 (cfcf1409...) -> 1 keys | 5462 slots | 1 slaves.
[OK] 1 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 198.20.0.31:6379)
M: b244b72fc5375c7e559ccb02aff9992e0d1aa0d0 198.20.0.31:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 183e2e42276ab7a4dfdfb426cb3e01a65a038362 198.20.0.33:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 91c8156bd7afd58c252d09ea416b68abbd3ddb49 198.20.0.35:6379
slots: (0 slots) slave
replicates b244b72fc5375c7e559ccb02aff9992e0d1aa0d0
S: 7cf393d7371a927104ae861cdb8dc675f2a35281 198.20.0.36:6379
slots: (0 slots) slave
replicates cfcf14091a752771d47e092321e3f4ade75f6de7
S: df71e5c164e2f99e41b1a951d7bc60c6e9daa7eb 198.20.0.34:6379
slots: (0 slots) slave
replicates 183e2e42276ab7a4dfdfb426cb3e01a65a038362
M: cfcf14091a752771d47e092321e3f4ade75f6de7 198.20.0.32:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
输入下面命令进入对应的docker服务:
docker exec -it redis-cluster-redis-master-1 /usr/local/bin/redis-cli -c -a test123 -h 198.20.0.31 -p 6379
然后进行一些集群信息访问:
目前可以确认服务内部的ok的,至于最开始无法命令get是因为从节点一般做备份,不允许读取,所以得开readonly命令。
4.2、一些问题
在进行docker compose down
或者docker compose stop
命令后,再次重启会提示。
[ERR] Node XXX is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
在google查了许久没有头绪,只能每次重启前进行数据清理。
删除每个redis下的appendonly.aof、dump.rdb、xxx.conf文件。
例如我在redis-cluster目录下时执行这个命令。
rm -rf data/*/*
第二个问题是无法进行外部连接访问,任何redis的连接器包括原生的redis-cli,在docker宿主机的情况下,无法连接内部集群,只能通过容器内部访问。
结语
目前搭建redis单机是没问题的,按自己思路搭建集群也没问题,后面发现无法通过宿主机外部连接访问,进行了各种查询,也尝试过海外其他人的方案,都无法让外部宿主机进行访问。
我认为可能有其他方式,或者配置上的问题,目前研究时间有限,等后续抽时间研究好了,再更新文档。