解决docker容器的目录权限的总结
背景
1 | version: '3' |
部署mysql的时候,将mysql目录进行挂载时提示
1 | cannot read directory '/var/lib/mysql/': Permission denied |
原因
我们聚集到entrypoint.sh这个文件,因为docker的镜像变成运行态的时候,也就是容器的时候,是需要命令来启动的,这个启动的命令就是entrypoint.sh,也就是说,启动的这个文件肯定是篡改了原来的目录,下面具体看下这个文件的某个关键代码片段
1 | # allow the container to be started with `--user` |
这段代码的意思是说,该程序运行指定用户来启动mysql,但是如果你不指定用户,他会默认用mysql用户来给DATADIR赋权限,并用mysql用户来执行脚本,所以实际上,用户就变mysql了,但是为啥在宿主机上,却是polkitd呢?
1 | // 容器内查看用户名为`mysql` 对应的用户ID和组ID为`999` |
1 | // 宿主机器查看999所对应的用户名 |
如上图,可以看到,在容器内部,他的用户为mysql,他的用户ID为999,然后退出容器,在宿主机上,可以看到ID为999的用户ID对应的用户变成了polkitd,所以,到了这里就明白了,实际上容器内部和外部是用的同一套用户,名字可能不同,但是ID用的是同一个,从而导致,ID虽然相同,但是用户不一致,从而权限也出现了差别。
1、其实在操作系统中,真正决定用户和用户组的东西并不是用户名和组名,而是相应的用户id 和 对应的组id,当我们刚创建用户时系统就会给用户分配对应的用户id 和 组id,可以在/etc/passwd中查看
2、在遇到的问题描述中,因为容器中只创建了一个mysql用户和组,因此容器中查看到mysql用户id和组id为999:999,因此给/var/lib/mysql
目录用户权限时其实是给予的用户id和组id为999:999权限,因此,在宿主机中./data
此目录的用户权限也变为999:999,因为宿主机中此用户id和组id对应的为polkitd,因此就显示为polkitd。
解决
方法1 推荐
在配置my.cnf时,指定error-log的位置在/var/log/
下,否则error的默认位置为例如/var/lib/mysql
下的mysqld.log文件因为目录映射后有权限问题,写入不了日志。
方法2
宿主机器更改与docker相同的用户ID和组id
chown 999
方法3
同步宿主/etc/passwd
到容器内,从而达到宿主和容器内相同的用户id和组ID
1 | [root@localhost ~]# getenforce |
实验
一直以来比较困惑容器挂载卷的文件权限问题,今天特地梳理下docker的挂载卷权限问题
首先,本地挂载点新建测试文件test.txt,然后将该目录挂载到容器的test目录
可以看到我们在容器外新建的test.txt文件在容器内的所有者变成了1000,然后我们在容器内新建文件查看容器外的权限,发现容器中新建的test1.txt所有者变成了root
接着查看下UID:1000所属用户
最后我们在指定wag用户启动docker,然后在容器内新建test3.txt文件,查看文件所有者
从以上可以得出,docker启动容器如果不指定用户,会默认以root(UID=0)方式运行,导致其中新建的文件所有者映射到容器外为root,容器外新建的文件映射到容器内所有者UID不变。