虽然其他网站上有大量关于Docker创建Redis集群的文章,但大多数都比较片面(感觉还是无脑复制粘贴,错误百出),所以决定重新整理一下,把遇到的问题都记录下来。
获取Redis镜像
首先从Docker Hub或其他镜像仓库中获取Redis镜像,这里我使用了Docker官方提供的Redis镜像,运行下面命令获取Redis镜像:
1 | sudo docker pull ubuntu |
镜像下载完毕后,执行sudo docker images
命令查看结果:
1 | REPOSITORY TAG IMAGE ID CREATED SIZE |
可以看到redis
和ubuntu
两个镜像已经获取成功,下面开始配置。
配置Redis集群
在配置Redis集群之前,需要一个redis.conf
的配置文件,该配置文件可以从Redis官方站点获取:
1 | wget -c http://download.redis.io/redis-stable/redis.conf |
等待下载完毕后,将redis.conf
拷贝三份,并依次重命名为:redis-master.conf
,redis-slave1.conf
,redis-slave2.conf
,将三个文件放在/home/liuwei/docker/redis/
目录中,看起来像这样:
1 | /home/liuwei/docker/redis/redis-master.conf |
注:这三个文件存放的位置无特殊要求,可以指定任意位置。
将redis-master.conf
文件中的配置项做如下修改:
1 | daemonize yes |
将redis-slave1.conf
和redis-slave2.conf
文件中的配置项做如下修改:
1 | daemonize yes |
slaveof
默认是注释掉的,只需要开启注释即可。需要注意的是slaveof
的格式为slaveof <masterip> <masterport>
,上面配置中masterip
参数为master
,实际上是一个别名,稍后会对它进行解释。配置完成后,下一步就是创建Docker容器并启动了。
创建Redis容器
创建Redis容器只需要使用第一步下载好的Redis镜像,调用Docker的run
命令即可,不过要创建一个Redis集群,还需要处理容器与容器之间的通信问题(即Redis的主从复制需要容器之间能够相互连通),这里使用docker run
命令的--link
参数来建立容器之间的相互连通。
简单介绍一下--link
这个参数,--link
的使用格式为:name:alias
,可以在docker run
命令中重复使用该参数,例如:
1 | sudo docker run -it --name ubuntu ubuntu /bin/bash |
上述命令将使用镜像创建一个名为ubuntu
容器,然后创建一个名为redis
的容器,将该容器连接到ubuntu
容器上。通过--link
参数连接的两个容器,可以避免容器的IP和端口暴露到外网导致的安全问题,以及容器在重启后IP地址变化导致访问失效。当容器的IP发生变化时,Docker会自动维护容器中的hosts文件,如果你打开两个通过--link
参数连接的容器中的某个容器的/etc/hosts
文件,你将看到如下内容:
1 | 127.0.0.1 localhost |
通过--link
参数,我们可以创建包含一个master
和两个slave
的Redis集群,使用如下命令创建:
1 | sudo docker run -it -v /home/liuwei/docker/redis/redis-master.conf:/usr/local/etc/redis/redis.conf --name redis-master redis /bin/bash |
上述命令中使用--link redis-master:master
参数,前面提到的redis-slave.conf
配置文件中slaveof
配置项,这里使用了一个master
作为别名,其效果和使用IP一样(IP地址在/etc/host
文件中)。
需要注意的是-v
参数,-v
参数用于将宿主机上的某个目录挂载到容器中。由于容器都是轻量化设计,只包含运行时的必须文件,所以在容器中使用vim
之类的命令很不方便(可能需要自行安装vim编辑器),所以我们将之前配置好的redis.conf
文件挂载到对应的容器中。因此,我们可以直接在宿主机上使用vim
命令或其他文本编辑器编辑redis.conf
文件。
-v
的格式为:-v /host/path:/container/path
,前部分表示主机的目录,后部分表示容器的目录(如果目录不存在,容器启动的时候会自行创建)。
容器启动完毕后,可以运行sudo docker ps
查看容器启动状态:
1 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
接下来是启动redis
服务,这里推荐为每个容器分配一个shell
窗口,方便直接在容器内执行命令。先启动master
,然后启动slaver
。分别在master
、slave1
和slave2
中运行启动redis
服务的命令:
1 | redis-server /usr/local/etc/redis/redis.conf |
启动后,在master
容器中执行下面的命令查看redis
服务的运行状态:
1 | redis-cli |
结果为:
1 | # 此处已省略 |
这里有个坑需要注意一下,我在配置完毕后启动容器,运行info
命令查看到上述信息中connected_slaves
的值为0,测试主从复制也没有成功,后来搜索了相关资料,需要将redis-master.conf
文件中的bind 127.0.0.1
修改为bind 0.0.0.0
,修改完毕后重启master
服务即可。
评论区有小伙伴提到按照上述修改
bind
属性后主从依然无法连通,可以尝试将redis-slave1.conf
和redis-slave2.conf
两个文件都改成bind 0.0.0.0
。
可以看到master
中已经包含两个slave
,接下来我们测试一下主从复制是否成功,在master
容器中输入下面的命令:
1 | 127.0.0.1:6379> set master liuwei |
然后分别在slave1
和slave2
容器中执行:
1 | 127.0.0.1:6379> get master |
如果能成功看到输出信息,说明主从复制成功。
相比使用虚拟机搭建Redis集群环境,Docker显得更简单轻量,如果需要配置更多slave
,只需要使用命令创建一个容器,连接到master
容器。