背景
今天朋友请教了我一个关于redis自定义配置的问题,他使用的是dockerhub官方redis镜像,运行命令如下:
docker run -p 6379:6379 --name redis -v /data/redis/redis.conf:/etc/redis/redis.conf -v /data/redis/data:/data -v /data/redis/log/redis-server.log:ar/log/redis/redis-server.log -d redis redis-server /etc/redis/redis.conf --appendonly yes
run命令的参考依据来源于网上搜到的一些答案;
问题是,启动后容器马上退出!且排除是因为内存不够导致容器退出的原因。(关于容器因内存退出,可以docker inspect 容器id,查看OOMKilled的值是不是true,是的会就是因为内存不够导致容器退出)
注意:
/data/redis/redis.conf的配置文件,他是有所改动的,关于logfile的配置从“”改为了/var/log/redis/redis-server.log;意思是把日志从控制台输出重定向到特定文件!
探究
dockerhub 官方redis镜像,建议是如何自定义修改配置文件呢?如下:
显然,我的朋友选择了第二种方法,因为他没有使用自定义镜像!
现在我们来做第一个测试,使用官网给出的第二种方法,但是区别是我简化了run命令,不挂在日志、data,且暂时不修改redis.conf,命令如下:
docker run --name junsi-redis -v /home/wzp/myredis/conf:/usr/local/etc/redis -d redis:latest redis-server /usr/local/etc/redis/redis.conf
结果是正常的,容器启动后并不会退出!
那接着,我们做第二个测试,在官方的redis.conf的基础上做一些自定义的改动,修改logfile为/var/log/redis/redis-server.log,再运行第一个测试的命令:
[root@mapt-test conf]# docker run --name junsi-redis -v /home/wzp/myredis/conf:/usr/local/etc/redis -d redis:latest redis-server /usr/local/etc/redis/redis.conf
-bash: docker run --name junsi-redis -v /home/wzp/myredis/conf:/usr/local/etc/redis -d redis:latest redis-server /usr/local/etc/redis/redis.conf: No such file or directory
[root@mapt-test conf]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
失败了!报错是:解析不到/usr/local/etc/redis/redis.conf的文件!
然后,去dockerhub redis提供的Dockfile对应的github仓库,找了一下历史的issue,https://github.com/docker-library/redis/issues/
没有找到关于使用挂载配置的方式,来自定义redis.conf出现 No such file or directory的解决方法!
最终为了解决这个问题,只能使用redis官方提供的第一种方式,也就是基于官方的基础redis镜像,做一个自定义配置文件的覆盖操作!
Dockerfile如下:
FROM redis
COPY redis.conf /usr/local/etc/redis/redis.conf
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
找一个目录存放redis.conf,redis.conf里面请根据你的需求,设置自定义的配置!我这里只是修改了logfile,指定了存日志的文件为容器内的地址,/var/log/redis/redis-server.log
(特殊说明,如果你的自定义配置涉及一些文件或目录,且这些文件目录在源镜像启动的容器中,本身没有,且你也没有在run的时候挂载映射文件或目录,那么你就需要在Dockfile里面提前创建这些文件或目录)
然后,构建新镜像:
[root@mapt-test conf]# ls
redis.conf
[root@mapt-test conf]# vi redis.conf
[root@mapt-test conf]# vi Dockerfile
[root@mapt-test conf]# docker build -t wzp/custom-redis:6.0 .
Sending build context to Docker daemon 88.58kB
Step 1/3 : FROM redis:latest
---> 621ceef7494a
Step 2/3 : COPY redis.conf /usr/local/etc/redis/redis.conf
---> 49b9c9648d8c
Step 3/3 : CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
---> Running in c8f695c48d12
Removing intermediate container c8f695c48d12
---> 398d1e08d366
Successfully built 398d1e08d366
Successfully tagged wzp/custom-redis:6.0
[root@mapt-test conf]# docker images | grep 'redis'
wzp/custom-redis 6.0 398d1e08d366 11 seconds ago 104MB
最后的启动命令是:
docker run -p 6379:6379 --name redis -v /home/wzp/myredis/conf:/usr/local/etc/redis -v /home/wzp/myredis/data/:/data/ -v /home/wzp/myredis/log/:/var/log/redis/ -d wzp/custom-redis:6.0
db7c6b6572fae0195337bd1ff6f7d0b79de18635eec9266774c1a7b17c209a78
[root@mapt-test conf]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@mapt-test conf]# docker logs db7c6b6572fae0195337bd1ff6f7d0b79de18635eec9266774c1a7b17c209a78
*** FATAL CONFIG FILE ERROR (Redis 6.0.10) ***
Reading the configuration file, at line 260
>>> 'logfile "/var/log/redis/redis-server.log"'
Can't open the log file: Permission denied
报错的意思是,需要设置挂载的宿主机源文件的权限,chmod -R 777 /xxx就行!
最终,
[root@mapt-test wzp]# docker run -p 6379:6379 --name redis -v /home/wzp/myredis/conf:/usr/local/etc/redis -v /home/wzp/myredis/data/:/data/ -v /home/wzp/myredis/log/:/var/log/redis/ -d wzp/custom-redis:6.0
ee8f64eef41aab577a31ed37e881dcf8449cce29ff536c12449013f1702e8d78
[root@mapt-test wzp]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee8f64eef41a wzp/custom-redis:6.0 "docker-entrypoint.s…" 2 seconds ago Up 2 seconds 0.0.0.0:6379->6379/tcp redis
其实docker run -v 涉及了一些文件、目录映射,会自动创建目录的知识点;比如上面那个权限报错,实际上就是因为run的时候,我宿主机上没有特定目录,docker帮我创建了宿主机目录,但是目录的权限不够,导致的问题;
后续补充:
docker run --privileged=true -p 6379:6379 --name redis -v /home/wzp/myredis/log/:/var/log/redis/ -v /home/wzp/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /home/wzp/myredis/data/:/data/ -d redis:latest redis-server /usr/local/etc/redis/redis.conf
官网的第二种方式,也是可以生效的,但是docker run需要加上--privileged=true选项!
我的docker版本:
[root@mapt-test log]# docker -v
Docker version 18.03.1-ce, build 9ee9f40
那么新问题来了,--privileged=true选项到底表示什么意思,什么时候启动容器时,需要加上这个选项?看了一些文章,但是还是有点云里雾里,但是可以确定的一点是,使用这个选项,才可以挂载redis.conf成功!
[root@mapt-test log]# docker run --name junsi-redis -d redis:latest
0f2bd76f650818db8f6163e3ccf2283739427eee6d6ef384b27eb21e0ed688ff
[root@mapt-test log]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0f2bd76f6508 redis:latest "docker-entrypoint.s…" 2 seconds ago Up 1 second 6379/tcp junsi-redis
[root@mapt-test log]# docker exec -it 0f2bd76f6508 /bin/bash
root@0f2bd76f6508:/data# whereis redis.conf
redis.conf:
root@0f2bd76f6508:/data#
上面这个截图的意思是什么?意思是官方镜像里面本身就没有redis.conf,那么容器默认不挂在redis.conf的配置文件,容器启动的配置是个什么配置?!
另外,貌似有说法是尽量不要使用--privileged=true,有安全风险?!
所以,综上所述,修改redis的配置文件,还是的基于官方基础镜像,自定义Dockerfile实现!!!
参考文档:
https://zhuanlan.zhihu.com/p/30555962
https://www.cnblogs.com/kerwincui/p/12544603.html
https://www.codenong.com/38112968/
https://www.jianshu.com/p/f79418acd312