Docker挂载文件默认777权限致MariaDB报错,求更优解决方案
问题背景
我把本地的mariadb.cnf以只读模式挂载到MariaDB 10.11容器里的/etc/mysql/mariadb.conf.d/80-app.cnf,docker-compose配置如下:
db: image: mariadb:10.11 volumes: - ./mariadb.cnf:/etc/mysql/mariadb.conf.d/80-app.cnf:ro
结果容器启动时弹出警告:
2023-06-14 18:27:16 Warning: World-writable config file '/etc/mysql/mariadb.conf.d/80-app.cnf' is ignored.
查了下容器内的文件权限,发现挂载后的80-app.cnf是777权限:
# ls -la /etc/mysql/mariadb.conf.d/ total 40 drwxr-xr-x 1 root root 4096 Jun 14 18:27 . drwxr-xr-x 1 root root 4096 Jun 9 23:30 .. -rw-r--r-- 1 root root 46 Jun 9 23:30 05-skipcache.cnf -rw-r--r-- 1 root root 575 Jun 5 19:14 50-client.cnf -rw-r--r-- 1 root root 231 Jun 5 19:14 50-mysql-clients.cnf -rw-r--r-- 1 root root 927 Jun 5 19:14 50-mysqld_safe.cnf -rw-r--r-- 1 root root 3584 Jun 9 23:30 50-server.cnf -rw-r--r-- 1 root root 570 Jun 5 19:14 60-galera.cnf -rwxrwxrwx 1 root root 167 Jun 14 16:39 80-app.cnf
临时解决办法是先删掉ro选项,进容器执行chmod 644 /etc/mysql/mariadb.conf.d/80-app.cnf,重启后再加回ro。但每个新用户首次启动都得这么操作,太麻烦。我想过在docker-entrypoint.sh里加这段脚本:
#!/bin/sh chmod 644 /etc/mysql/mariadb.conf.d/*-app.cnf
但有没有更靠谱的方案?
可行的更优方案
1. 直接改宿主机文件权限
这是最直接的办法,在宿主机上把本地的mariadb.cnf权限改成644:
chmod 644 ./mariadb.cnf
Docker挂载文件时会继承宿主机的权限设置,这样容器里的文件权限就会是-rw-r--r--,完全符合MariaDB的要求,后续启动容器直接用原来的ro配置就行。
2. 用Docker Compose挂载时指定权限(Docker 20.10+)
如果你的Docker版本在20.10及以上,支持在volume挂载时直接指定权限,不用改宿主机文件:
db: image: mariadb:10.11 volumes: - ./mariadb.cnf:/etc/mysql/mariadb.conf.d/80-app.cnf:ro,uid=0,gid=0,mode=0644
这里uid=0和gid=0对应root用户,mode=0644把文件权限设为root可写、其他用户只读,完美适配MariaDB的安全要求。
3. 构建自定义MariaDB镜像
如果你的配置比较固定,不想让用户折腾,可以自己做个自定义镜像,把配置文件直接打包进去并设置好权限:
先写个Dockerfile:
FROM mariadb:10.11 COPY mariadb.cnf /etc/mysql/mariadb.conf.d/80-app.cnf RUN chmod 644 /etc/mysql/mariadb.conf.d/80-app.cnf
然后构建镜像:
docker build -t custom-mariadb:10.11 .
最后修改docker-compose用这个自定义镜像:
db: image: custom-mariadb:10.11 # 不需要再挂载本地文件,除非你需要动态修改配置
这种方式用户直接启动容器就行,完全不用管权限的事。
4. 加个init容器预处理权限
如果必须挂载本地文件,又不想改宿主机权限,可以加个init容器,在MariaDB主容器启动前先把挂载文件的权限改好:
services: db-init: image: alpine:latest command: chmod 644 /config/80-app.cnf volumes: - ./mariadb.cnf:/config/80-app.cnf db: image: mariadb:10.11 volumes: - ./mariadb.cnf:/etc/mysql/mariadb.conf.d/80-app.cnf:ro depends_on: db-init: condition: service_completed_successfully
init容器会先启动,改完权限后退出,主容器再启动,确保挂载的文件权限正确。
内容的提问来源于stack exchange,提问作者gremo

