草庐IT

分析docker启动MySQL挂载目录提示权限不足Permission denied原因

jiangyunfan16 2024-02-13 原文

分析docker启动MySQL挂载目录提示权限不足Permission denied原因

测试如果使用挂载目录不开放目录权限

拉取 MySQL 镜像使用版本8.0.30

docker pull mysql:8.0.30

创建挂载目录文件夹添加自定义配置文件

## 创建挂载目录
[zhangsan@localhost /]$ mkdir -p /home/zhangsan/mysql/{logs,data,conf}

## 创建编辑自定义配置文件
[zhangsan@localhost /]$ vim /home/zhangsan/mysql/conf/my.cnf

## 加入下面内容
[mysqld]
 # 指定数据目录
 datadir=/var/lib/mysql
 # 服务端字符集
 character-set-server=utf8mb4
 # 字符集排序规则
 collation-server=utf8mb4_unicode_ci
 # error日志路径
 log-error=/var/log/mysql/error.log
 # 开启慢查询 1:开启	  【可选】
 slow_query_log=1
 # 定义3秒以上为慢查询	【可选】 
 long_query_time=3
 # 慢查询日志路径		  【可选】	
 slow-query-log-file=/var/log/mysql/slow.log	
[client]
 default-character-set=utf8mb4
[mysql]
 default-character-set=utf8mb4

不开放目录权限直接docker命令启动 MySQL

docker run --name mysql \
-v /home/zhangsan/mysql/data:/var/lib/mysql \
-v /home/zhangsan/mysql/conf:/etc/mysql/conf.d \
-v /home/zhangsan/mysql/logs:/var/log/mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=[密码] \
--net halo-net \
--restart=unless-stopped \
-d mysql:8.0.30

执行 docker ps 查看发现没有启动成功

执行 docker logs [容器ID] 查看错误信息

docker logs a56788d8a9e0

发现出现上述报错提示,无法打开/var/log/mysql/error.log 文件因为权限不足。

网上很多说在启动的时候加上 --privileged=true 赋予docker内容器充分的root权限就可以了,经实测这种启动方式对于centos8 或者 aliyunLinux 是没有效果的而且本质问题也不在于root权限!

初步分析权限不足的原因

执行命令创建临时mysql容器并查询当前容器内mysql目录以及mysql用户权限

docker run -ti --rm  --entrypoint="/bin/bash" mysql:8.0.30 -c "cat /etc/group

docker run -ti --rm  --entrypoint="/bin/bash" mysql:8.0.30 -c "ls -la /var/lib/"

默认docker中使用的是mysql 用户权限,而在docker 容器内环境中mysql用户组id是 999

而宿主机中用户zhangsan的用户组id是1000,所以当挂载目录的时候会提示没有权限,所以解决办法就是将宿主机中对应目录的 [user] [group] [other] 中的[other]一项改成可读可写 rw-

当然最简单的办法是直接授予这个目录777全开放权限(所有人可读可写可执行)

chmod -R 777 /home/zhangsan/mysql

这样宿主机在挂载目录文件的时候就可以了,修改目录权限重新执行后发现mysql已经顺利启动了

当然如果只是这么简单介绍相信各位点进来的技术大佬们要吐槽了,所以我们继续往下探究最小开放目录权限以及为什么会产生这种问题的原因。

详细分析权限不足的原因

1.分析数据目录为什么是属于名为polkitd的用户

查看刚才未修改用户权限时的挂载目录data 它的所属用户是一个叫polkitd的用户???

drwxrwxr-x 6 polkitd            polkitd  4096 Jul 25 12:01 data

大家可能会感到迷惑,为什么这个data目录挂载之后的权限中出现一个polkitd的用户?为什么我用zhangsan账号权限下创建的data目录中会出现其他用户的权限文件?【难道被隔壁老王绿了?🤔】

查看这个polkitd的用户id 貌似有什么惊天发现,

polkitd:x:999:

这个polkitd的用户组id居然是999,相信这个时候已经有不少人反应过来了,这不是容器中mysql的用户组id么?

原因就在这里了,原来在mysql的docker启动文件中指明 可以在启动的时候通过 --user 指定启动用户

# allow the container to be started with `--user`
if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then
        _check_config "$@"
        DATADIR="$(_get_config 'datadir' "$@")"
        mkdir -p "$DATADIR"
        chown -R mysql:mysql "$DATADIR"
        exec gosu mysql "$BASH_SOURCE" "$@"
fi

如果不指定则默认使用mysql用户权限,注意上面会使用mysql用户创建数据目录 $DATADIR 然后并授予该目录用户和用户组为mysql 所以当把这个目录挂载出去的时候该目录的用户和用户组是 999 而在宿主机中 999对应的用户是

polkitd,所以说明容器内外对应的用户权限实际使用的是ID 关联而不是用户名。

2.需要修改权限的最小目录范围是什么?

  1. 经过上述分析看出数据目录是容器内mysql启动时用mysql账号权限创建的,所以挂载出来后,通过用户id保持关联,容器内的mysql用户权限目录可以读写宿主机的数据目录
  1. 对于配置文件目录,只要保证在容器内可以读取到宿主机的配置文件即可,通过查看权限发现配置文件权限对于其他用户的策略是可读 r–
  2. 对于日志文件目录,容器内在mysql启动时需要读写宿主机挂载出来的日志文件,通过查看权限发现该文件对于其他用户策略时不可读写的 --x

综上可以看出,最小的目录开放权限就是把日志目录权限改成全开放即可,下面进行实验。

首先使用 docker rm [容器ID] 命令把上面创建成功的docker中的mysql 镜像删除

docker rm a56788d8a9e0

然后把对应挂在的目录也删掉

rm -rf /home/zhangsan/mysql

重新按照上述第一步骤中创建并修改好需要挂在的目录以及自定义配置文件 【见第一步创建挂载目录文件夹添加自定义配置文件】

然后我们只修改logs目录权限

chmod -R 777 /home/zhangsan/mysql/logs

执行启动命令并查看mysql容器是否正常启动

docker run --name mysql \
-v /home/zhangsan/mysql/data:/var/lib/mysql \
-v /home/zhangsan/mysql/conf:/etc/mysql/conf.d \
-v /home/zhangsan/mysql/logs:/var/log/mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=[密码] \
--net halo-net \
--restart=unless-stopped \
-d mysql:8.0.30

发现容器已经正常启动了,进入容器也没有问题👌。

所以如果你不想挂载日志目录的话,单纯挂载数据目录是不需要修改权限的。但是为了查看日志方便还是推荐挂载到自定义的目录中,方便查看错误日志或者慢查询日志。

3.补充:通过指定启动容器时的用户避免修改目录权限

如果想挂载日志目录但不想修改目录权限也有办法:

第1步分析中可以在启动时指定容器启动的用户权限,但要注意传递的是用户的ID号,如果把zhangsan的用户号1000通过启动参数 – user:1000 传入则容器内的mysql创建者就不再是默认ID 号为999的mysql用户了,这样挂载出来的时候对应的1000用户号就是你当前的用户zhangsan,这样挂载目录所有者为zhangsan,当然就不会出现读取目录文件时用户权限不足的问题了。

命令如下:

docker run --name mysql \
-- user 1000
-v /home/zhangsan/mysql/data:/var/lib/mysql \
-v /home/zhangsan/mysql/conf:/etc/mysql/conf.d \
-v /home/zhangsan/mysql/logs:/var/log/mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=[密码] \
--net halo-net \
--restart=unless-stopped \
-d mysql:8.0.30

启动成功后查看对应的目录权限:

drwxrwxr-x 2 zhangsan           zhangsan 4096 Jul 25 11:43 conf
drwxrwxr-x 6 zhangsan           zhangsan 4096 Jul 25 12:01 data
drwxrwxrwx 2 zhangsan           zhangsan 4096 Jul 25 11:47 logs

此时发现对应的data已经变成zhangsan了启动也正常,至此权限不足的问题就解决了。

有关分析docker启动MySQL挂载目录提示权限不足Permission denied原因的更多相关文章

  1. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  2. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  3. ruby-on-rails - 如何在 Gem 中获取 Rails 应用程序的根目录 - 2

    是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在

  4. UE4 源码阅读:从引擎启动到Receive Begin Play - 2

    一、引擎主循环UE版本:4.27一、引擎主循环的位置:Launch.cpp:GuardedMain函数二、、GuardedMain函数执行逻辑:1、EnginePreInit:加载大多数模块int32ErrorLevel=EnginePreInit(CmdLine);PreInit模块加载顺序:模块加载过程:(1)注册模块中定义的UObject,同时为每个类构造一个类默认对象(CDO,记录类的默认状态,作为模板用于子类实例创建)(2)调用模块的StartUpModule方法2、FEngineLoop::Init()1、检查Engine的配置文件找出使用了哪一个GameEngine类(UGame

  5. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  6. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  7. ruby-on-rails - 没有这样的文件或目录 - 用 Mini Magick 识别 - 2

    在我让另一个人重做我的前端UI之前,我的Rails应用程序运行平稳。我已经尝试解决此错误3天了。这是错误:Nosuchfileordirectory-identifyExtractedsource(aroundline#59):575859606162@post=Post.find(params[:id])authorize@postif@post.update_attributes(post_params)flash[:notice]="Postwasupdated."redirect_to[@topic,@post]else{"utf8"=>"✓","_method"=>"patc

  8. ruby - 是否可以将 IRB 提示配置为动态更改? - 2

    我想在IRB中浏览文件系统并让提示更改以反射(reflect)当前工作目录,但我不知道如何在每个命令后进行提示更新。最终,我想在日常工作中更多地使用IRB,让bash溜走。我在我的.irbrc中试过这个:require'fileutils'includeFileUtilsIRB.conf[:PROMPT][:CUSTOM]={:PROMPT_N=>"\e[1m:\e[m",:PROMPT_I=>"\e[1m#{pwd}>\e[m",:PROMPT_S=>"FOO",:PROMPT_C=>"\e[1m#{pwd}>\e[m",:RETURN=>""}IRB.conf[:PROMPT_MO

  9. ruby - Sinatra 找不到 View 目录 - 2

    我正在尝试以一种更类似于普通RubyGem结构的方式构建我的Sinatra应用程序。我有以下文件树:.├──app.rb├──config.ru├──Gemfile├──Gemfile.lock├──helpers│  ├──dbconfig.rb│  ├──functions.rb│  └──init.rb├──hidden│  └──Rakefile├──lib│  ├──admin.rb│  ├──api.rb│  ├──indexer.rb│  ├──init.rb│  └──magnet.rb├──models│  ├──init.rb│  ├──invite.rb│  ├─

  10. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

随机推荐