## CentOS Docker 安装
## 前言
> 警告!此文章搭建的redis集群经实践有部分bug。需要搭建的[点击新版搭建教程][],已修复本文出现的bug。
使用docker-compose和redis官方镜像和第三方redis-trib镜像组建3主3从的redis集群并设置密码。
## 构建文件结构
```bash
#新建文件夹
mkdir -p /mnt/docker/redis
#在redis文件夹下新建docker-compose.yml文件
cd /mnt/docker/redis
touch docker-compose.yml
#在redis文件夹下新建slave1到slave6共6个文件夹作为从属结点的文件夹
mkdir slave{1,2,3,4,5,6}
```
- 文件结构如下
![][image-1]
## 编写redis.conf文件
- 下载官方文件
```bash
wget http://download.redis.io/redis-stable/redis.conf
```
- 修改文件配置
```bash
# bind 127.0.0.1 //加上注释#
protected-mode no //关闭保护模式
port 6061 //绑定自定义端口
#daemonize yes //禁止redis后台运行
pidfile /var/run/redis_6061.pid
cluster-enabled yes //开启集群 把注释#去掉
cluster-config-file nodes_6061.conf //集群的配置 配置文件首次启动自动生成
```
> 注意:此处只是slave1节点的配置,后续的5个节点的配置文件按此规则配置并修改端口即可。
>
> - requirepass和masterauth不能启用
> 因为使用redis-trib连接集群时是不能指定密码的,如果开启了requirepass或者masterauth会导致集群连接失败,所以应该等集群创建好后再修改密码
> - bind
> 表示设置redis监听哪个ip,设置了监听之后,只有使用这些ip才能访问这个redis服务,不指定则默认所有ip都能访问该redis服务
> 注意:这里的ip指的是redis的ip而非访问方的ip,bind并不直接限制哪些ip能够访问redis,显示ip访问是限制监听后的效果,如果想限制ip访问应使用Linux防火墙功能
> 比方说,在生产条件下的redis服务器有3个ip(外网ip 122.122.122.122,局域网ip192.128.0.1,本地ip127.0.0.1),则为了安全,bind后面只应该写局域网ip和本地ip,这样就只有局域网用户(包括本机)可以通过192.128.0.1访问redis服务,间接起到限制ip访问的作用
> - protected-mode
> - 作用:禁止公网访问redis cache,加强redis安全的
> - 启用条件:
> - 没有bind IP
> - 没有设置requirepass访问密码
> - 解释:由于前面提及的原因,保护模式会开启导致无法通过公网访问,故这里需要关闭保护模式,但注意集群建好后要及时添加密码,增强安全性
> - daemonize 和 pidfile
> 实测开启守护模式(daemonize yes)容器会启动失败,因为是使用docker,所以前台启动也没什么关系,pidfile的文件名和端口号一致是一个良好的习惯
## 编写Dockerfile文件
> Dockerfile文件每个slave文件夹下都需要新增一个,可以编写好后使用cp命令复制到 各个文件夹
- 创建Docker文件
```bash
vim Dockerfile
```
- 继续编写文件,以slave1为例(6061)
```bash
#基础镜像
FROM redis
#将自定义conf文件拷入
COPY redis.conf /usr/local/etc/redis/redis.conf
#修复时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
#修改文件权限,使之可以通过config rewrite重写
RUN chmod 777 /usr/local/etc/redis/redis.conf
# Redis客户端连接端口
EXPOSE 6061
# 集群总线端口:redis客户端连接的端口 + 10000
EXPOSE 16061
#使用自定义conf启动
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
```
> 注意:此处只是slave1节点的配置,后续的5个节点的Dockerfile文件按此规则配置并修改端口即可。
>
> - 集群总线端口,需外网开放
> Redis集群中每个redis实例(可能一台机部署多个实例)会使用两个Tcp端口,一个用于给客户端(redis-cli或应用程序等)使用的端口,另一个是用于集群中实例相互通信的内部总线端口,且第二个端口比第一个端口一定大10000.内部总线端口通信使用特殊协议,以便实现集群内部高带宽低时延的数据交换。所以配置redis实例时只需要指明第一个端口就可以了。
> 但是由于我们使用的是docker,所以要将这个端口暴露出来,否则集群无法建立(使用redis-trib时会一直显示Waiting for the cluster to join)
> - 修改redis.conf文件权限,否则后面写入访问密码到文件的时候会提示`Permission denied`
## 编写docker-compose.yml文件
- 直接贴出,没什么好说的
```yaml
redis-slave1:
build: ./slave1
ports:
- 6061:6061
- 16061:16061
redis-slave2:
build: ./slave2
ports:
- 6062:6062
- 16062:16062
redis-slave3:
build: ./slave3
ports:
- 6063:6063
- 16063:16063
redis-slave4:
build: ./slave4
ports:
- 6064:6064
- 16064:16064
redis-slave5:
build: ./slave5
ports:
- 6065:6065
- 16065:16065
redis-slave6:
build: ./slave6
ports:
- 6066:6066
- 16066:16066
```
## 启动运行
- 在redis目录下(即docker-compose.yml同级目录)执行
```bash
docker-compose up -d
```
- 查看容器运行情况
```bash
docker-compose ps
```
![][image-2]
- 使用redis客户端连接测试,此时redis没有设置密码,集群状态也是失败的,但连接能成功。
![][image-3]
## 连接集群
- 集群配置比较简单,只需一条命令
```bash
docker run --rm -it zvelo/redis-trib create --replicas 1 ip:6061 ip:6062 ip:6063 ip:6064 ip:6065 ip:6066
```
> 此处ip替换成实际ip地址,结果如下,中间需要用yes来同意集群方案
![][image-4]
## 验证集群
- 输入`cluster info`查看集群信息,此时已为 `ok`,再测试一下set和get,另外可以看到,结点会自己切换,并且6061端口set和数据可以在6062端口get到
![][image-5]
## 设置集群密码
- 使用redis-trib.rb工具构建集群,集群构建完成前不要配置密码,集群构建完毕再通过config set + config rewrite命令`逐个机器`设置密码
- 如果对集群设置密码,那么`requirepass和masterauth`都需要设置,否则发生主从切换时,就会遇到授权问题
- 各个节点的`密码都必须一致`,否则Redirected就会失败
具体 指令:
```bash
#设置masterauth
config set masterauth 你的密码
#设置requirepass
config set requirepass 你的密码
#验证密码,以继续操作
auth 你的密码
#回写到文件,使其永久生效
config rewrite
```
> 注意:第三步的时候,如果出现Permission denied,则说明Dockerfile少了`RUN chmod 777 /usr/local/etc/redis/redis.conf`
![][image-6]
- 使用docker exec指令进入容器内部看一下masterauth和requirepass是否写入到文件里
```bash
docker exec -it 容器ID /bin/bash
```
- cat指令查看
```bash
cat /usr/local/etc/redis/redis.conf
```
![][image-7]
- 可以看到masterauth和requirepass被追加到文件的最后,即使重启密码也还生效
## 后记
至此,利用docker-compose组建redis集群结束
可以看到,其实docker-compose起的作用并不大,因为在单机上部署redis集群确实没什么实际意义,但是,你完全可以把slave结点放到不同的服务器上,再通过docker的redis-trib容器来连接,十分灵活和方便.
文章参考:[感谢鲸临于空][1]
[1]: https://blog.csdn.net/alinyua/article/details/80936940
[2]: https://blog.chihiro.org.cn/archives/20200415203000
[image-1]: https://blog.chihiro.org.cn/upload/2019/10/%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84-cfb9a1a0e5d3440dbdb9535eda480564.png
[image-2]: https://blog.chihiro.org.cn/upload/2019/10/%E5%AE%B9%E5%99%A8%E8%BF%90%E8%A1%8C%E6%83%85%E5%86%B5-826f7c7a8d7e49beb7ed82c8b5f6d772.png
[image-3]: https://blog.chihiro.org.cn/upload/2019/10/%E9%9B%86%E7%BE%A4%E5%A4%B1%E8%B4%A5%E7%8A%B6%E6%80%81-177b216ba5564619a0f09fab42d21d93.png
[image-4]: https://blog.chihiro.org.cn/upload/2019/10/%E9%9B%86%E7%BE%A4%E9%85%8D%E7%BD%AE-01edb244d6764a0e8f84f04087abc246.png
[image-5]: https://blog.chihiro.org.cn/upload/2019/10/%E9%9B%86%E7%BE%A4%E6%88%90%E5%8A%9F%E7%8A%B6%E6%80%81-533e59416f8447cb8ca9d9b0bee34d5e.png
[image-6]: https://blog.chihiro.org.cn/upload/2019/10/%E5%AF%86%E7%A0%81%E9%85%8D%E7%BD%AE-337f77db47314792894d0a1ab17c6bb1.png
[image-7]: https://blog.chihiro.org.cn/upload/2019/10/%E5%AF%86%E7%A0%81%E6%9F%A5%E7%9C%8B-4aac013eb9cb4e368d3b91af56a2751d.png

docke搭建redis集群