谈谈 Docker Volume 之权限管理(一)

2023-11-15

14651294671008

Volume数据卷是Docker的一个重要概念。数据卷是可供一个或多个容器使用的特殊目录,可以为容器应用存储提供有价值的特性:

  • 持久化数据与容器的生命周期解耦:在容器删除之后数据卷中的内容可以保持。Docker 1.9之后引进的named volume(命名文件卷)可以更加方便地管理数据卷的生命周期;数据卷可以被独立地创建和删除。
  • 数据卷可以用于实现容器之间的数据共享
  • 可以支持不同类型的数据存储实现

Docker缺省提供了对宿主机本地文件卷的支持,可以将宿主机的目录挂载到容器之中。由于没有容器分层文件系统带来的性能损失,本地文件卷非常适合一些需要高性能数据访问的场景,比如MySQL的数据库文件的存储。同时Docker支持通过volume plugin实现不同类型的数据卷,可以更加灵活解决不同应用负载的存储需求。比如在阿里云容器服务中可以为容器提供基于云盘的块存储、基于OSSFS和NAS/NFS的共享文件存储。

然而Docker数据卷的权限管理经常是非常令人困惑的。本文将结合实例给大家介绍Docker数据卷权限管理中的常见问题和解决方法。

从Jenkins挂载本地数据卷错误谈起

最近的一个同事在利用容器运行Jenkins时遇到一个问题,其复现步骤如下:

注:如果是Windows/Mac需要登录到Boot2docker虚拟机之上,而Linux无需如此。

docker-machine ssh default

启动Jenkins官方镜像,并检查日志

docker run -d -p 8080:8080 -p 50000:50000 --name jenkins jenkins
docker logs jenkins

我们可以发现"jenkins"容器日志显示结果一切正常

然而为了持久化Jenkins配置数据,当我们把宿主机当前目录下的data文件夹挂载到容器中的目录"/var/jenkins_home"的时候,问题出现了:

docker rm -f jenkins
docker run -d -p 8080:8080 -p 50000:50000 -v $(pwd)/data:/var/jenkins_home --name jenkins jenkins
docker logs jenkins

错误日志如下

touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

这是神马情况?

我们检查一下之前启动方式的"/var/jenkins_home"目录权限,查看Jenkins容器的当前用户: 当前用户是"jenkins"而且"/var/jenkins_home"目录是属于jenkins用户拥有的

docker@default:~$ docker run -ti --rm --entrypoint="/bin/bash" jenkins -c "whoami && id"
jenkins
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)

docker@default:~$ docker run -ti --rm --entrypoint="/bin/bash" jenkins -c "ls -la /var/jenkins_home"
total 20
drwxr-xr-x  2 jenkins jenkins 4096 Jun  5 08:39 .
drwxr-xr-x 28 root    root    4096 May 24 16:43 ..
-rw-r--r--  1 jenkins jenkins  220 Nov 12  2014 .bash_logout
-rw-r--r--  1 jenkins jenkins 3515 Nov 12  2014 .bashrc
-rw-r--r--  1 jenkins jenkins  675 Nov 12  2014 .profile

而当映射本地数据卷时,/var/jenkins_home目录的拥有者变成了root用户

docker run -ti --rm -v $(pwd)/data:/var/jenkins_home --entrypoint="/bin/bash" jenkins -c "ls -la /var/jenkins_home"
total 4
drwxr-sr-x  2 root staff   40 Jun  5 08:32 .
drwxr-xr-x 28 root root  4096 May 24 16:43 ..

这就解释了为什么当"jenkins"用户的进程访问"/var/jenkins_home"目录时,会出现 Permission denied 的问题

我们再检查一下宿主机上的数据卷目录,当前路径下"data"目录的拥有者是"root",这是因为这个目录是Docker进程缺省创建出来的。

docker@default:~$ ls -la data
total 0
drwxr-sr-x    2 root     staff           40 Jun  5 08:32 ./
drwxr-sr-x    5 docker   staff          160 Jun  5 08:32 ../

发现问题之后,相应的解决方法也很简单:把当前目录的拥有者赋值给uid 1000,再启动"jenkins"容器就一切正常了。

sudo chown -R 1000 data
docker start jenkins

这时利用浏览器访问 "http://192.168.99.100:8080/" 就可以看到Jenkins的Web界面了。注:如无法访问,可能需要通过docker-machine ip命令获得当前Docker宿主机的IP地址。

14651282061323

当我们再进入容器内部查看"/var/jenkins_home"目录的权限,其拥有者已经变成 "jenkins"

docker@default:~$ docker exec jenkins ls -la /var/jenkins_home
total 24
drwxr-sr-x 11 jenkins staff  340 Jun  5 09:00 .
drwxr-xr-x 28 root    root  4096 May 24 16:43 ..
drwxr-sr-x  3 jenkins staff   60 Jun  5 08:59 .java
-rw-r--r--  1 jenkins staff  289 Jun  5 08:59 copy_reference_file.log
...

而有趣的是在宿主机上我们看到的 "data"目录的拥有者是"docker",这是因为"docker"用户在"boot2docker"宿主机上的uid也是"1000"。

docker@default:~$ ls -la data
total 20
drwxr-sr-x    2 docker   staff           40 Jun  5 11:55 ./
drwxr-sr-x    6 docker   staff          180 Jun  5 11:55 ../
...

这时我们已经可以知道:容器的本地数据卷中文件/目录的权限是和宿主机上一致的,只是uid/gid在Docker容器和宿主机中可能映射为不同的用户/组名称。

在上文,我们使用了一个常见的技巧,即在宿主机上执行chown命令时采用了uid而不是具体的用户名,这样就可以保证设置正确的拥有者。

问题虽然解决了,但思考并没有结束。因为当使用本地数据卷时,Jenkins容器会依赖宿主机目录权限的正确性,这会给自动化部署带来额外的工作。有没有方法让Jenkins容器为数据卷自动地设置正确的权限呢?这个问题对很多以non-root方式运行的应用也都有借鉴意义。

为non-root应用正确地挂载本地数据卷

我们可以从万能的stackoverflow.com找到很多相关的讨论,其中一个非常有借鉴意义问答如下

http://stackoverflow.com/questions/23544282/what-is-the-best-way-to-manage-permissions-for-docker-shared-volumes

其中的基本思路有两个:

  • 一个是利用Data Container的方法在容器间共享数据卷。这样就规避了解决宿主机上数据卷的权限问题。由于在1.9版本之后,Docker提供了named volume来取代纯数据容器,我们还需要真正地解决这个问题。
  • 另外一个思路就是让容器中以root用户启动,在容器启动脚本中利用"chown"命令来修正数据卷文件权限,之后切换到non-root用户来执行程序

我们来参照第二个思路来解决这个问题

下面是一个基于Jenkins镜像的Dockerfile:它会切换到"root"用户并在镜像中添加"gosu"命令,和新的入口点"/entrypoint.sh"

FROM jenkins:latest
USER root
RUN GOSU_SHA=5ec5d23079e94aea5f7ed92ee8a1a34bbf64c2d4053dadf383992908a2f9dc8a \
  && curl -sSL -o /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.9/gosu-$(dpkg --print-architecture)" \
  && chmod +x /usr/local/bin/gosu \
  && echo "$GOSU_SHA  /usr/local/bin/gosu" | sha256sum -c - 
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

注释:gosu 是经常出现在官方Docker镜像中的一个小工具。它是"su"和"sudo"命令的轻量级替代品,并解决了它们在tty和信号传递中的一些问题。

新入口点的"entrypoint.sh"的内容如下:它会为"JENKINS_HOME"目录设置"jenkins"的拥有权限,并且再利用"gosu"命令切换到"jenkins"用户来执行"jenkins"应用。

#! /bin/bash
set -e
chown -R 1000 "$JENKINS_HOME"
exec gosu jenkins /bin/tini -- /usr/local/bin/jenkins.sh

您可以直接从 https://github.com/denverdino/docker-jenkins 获得相关代码,并构建自己的Jenkins镜像。执行命令如下:

git clone https://github.com/AliyunContainerService/docker-jenkins
cd docker-jenkins/jenkins
docker build -t denverdino/jenkins .

然后基于新镜像启动Jenkins容器

docker rm -f jenkins
docker run -d -p 8080:8080 -p 50000:50000 -v $(pwd)/data:/var/jenkins_home --name jenkins denverdino/jenkins

总结

本文介绍了Docker数据卷的基本概念。针对non-root进程访问本地数据卷出现的权限问题,我们给出了一个解决方案。我们计划在未来为大家继续总结在Docker数据卷上遇到的一些其他问题,

想了解更多容器服务内容,请访问 https://www.aliyun.com/product/containerservice

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

谈谈 Docker Volume 之权限管理(一) 的相关文章

  • 如何升级 Windows 中 git svn 使用的 SVN 版本?

    我的公司正在将SVN升级到1 7 检查git svn version显示正在使用的SVN版本是1 4 6 我想获得 git svn 使用的 SVN 版本接近 1 7 但是 我没有看到有关更新 git svn 使用的 SVN 版本 在 Win
  • Visual Studio Code 内置故事,用于查看 git 提交历史记录并对其内容进行比较

    In this https stackoverflow com questions 37899765 how can i view the git history in visual studio code 60013101 noredir
  • 在 Web 应用程序中显示最新的提交值?

    我有一些 Rails 应用程序 我使用 Git 作为版本控制系统 我使用 GitHub 或 Beanstalk 作为存储库主机 从理论上讲 我想要做的事情非常简单 以某种方式在 Web 应用程序的页脚中显示最新的提交 ID 号 哈希值 这样
  • git Blame:合并后正确的作者

    GIT 合并引入了新的提交 这会导致 git Blame 问题 合并的行似乎是由进行合并的开发人员提交的 我可以理解这种情况冲突的变化 因为他解决了冲突 但是有没有办法让非冲突线路不发生这种情况呢 一些 git Blame 的选择 如果没有
  • 我在哪里? *(无分支)

    我已经熟悉了创建 合并和删除分支 我想知道我在哪里 这样我就不会将工作提交到错误的分支 我用git branch a看看我有哪些分支 我认为星号 显示我当前所在的分支 当我得到以下信息时 这意味着什么 no branch master or
  • 从自己的 gitlab 服务器安装节点模块

    我想从我们的 gitlab 服务器安装节点模块 这是存储库的链接 http ABCD GITLAB myGroup myNodeModule git http ABCD GITLAB myGroup myNodeModule git 根据n
  • git 如何查找分支源自的提交哈希

    假设我从主分支分支到主题分支 然后在主题分支上进行了一些提交 是否有命令告诉我主题分支源自的主分支上的提交哈希 理想情况下 我不必知道我做了多少次提交 试图避免 HEAD 5 我已经用谷歌搜索过 但似乎无法找到答案 谢谢 use git m
  • 为什么 git-svn 应该积极搜索旧历史?

    当我运行 git svn clone s 时发生了一些奇怪的事情 尽管以下信息告诉我们不要惊慌 但我想知道为什么会出现这种 svn 错误 为什么这个路径不存在 是被别人删除了吗 如果是 为什么 git svn 应该积极搜索旧历史记录 Ini
  • 如何让 Gitlab 运行程序在成功构建时将代码合并到分支中

    嗯 标题几乎是不言自明的 总之 如果构建成功 我希望将一个分支 即开发 合并到另一个分支 即生产 我尝试了 jakub kania 解决方案 但我总是得到id rsa invalid format 我认为 gitlab 秘密变量以某种方式被
  • SSL 适用于浏览器、wget 和curl,但不适用于 git

    我有一个网站 用于托管 redmine 和几个 git 存储库 这非常适合 http 但我无法使用 https 进行克隆 即 git clone http mysite com git test git 工作正常 但是 git clone
  • 如何停用 Xcode git 功能? (删除 git 集成)

    我的 Xcode 项目位于 git 上 但我不喜欢 Xcode git 集成 有时 我有来自 Xcode 的错误 https stackoverflow com questions 7388560 error fatal not a git
  • 为什么cherry-pick 告诉我所有行都已更改?

    Updated 考虑文件 abc 在提交 A 和 B 中都相同 begin 123 456 789 klm end 在A中 我们重构第一行123 gt AAA并在结果之上选择 B Git 告诉我们all lines in the file
  • 合并后 Git 分支和提交历史记录

    我正在开发一个项目 单独 对于我开发的每个功能 我都会创建一个新分支 处理该功能 然后将其合并到 master 中 所以通常我不会同时在两个不同的分支上工作 也不会在一个分支上工作时接触master 当我合并一个分支时 我看到 使用gitx
  • 创建多个 git 分支的联合分支

    我希望能够在现有分支之上分层其他分支 并独立修改这些分支 这很有用 例如 允许将各个子项目的二进制文件统一到同一个项目中bin目录 一般来说 给定的文件仅存在于一层中 理想情况下 我想我会使用 unionfs 来完成此任务 但它必须以某种方
  • 在种子项目上构建时如何组织 git 存储库

    我正在基于从 github 克隆的种子项目 MEAN io 构建一个网站 如何将这些文件与我自己的文件分开 由于该种子提供了广泛的文件框架 因此我自己的文件分布在整个项目中 我希望能够从种子中提取更新 但不能将其与我添加的文件混合 我知道我
  • 如何在源代码管理中存储 Visual Studio 的调试配置

    Visual Studio 的调试配置存储在 user文件是用户特定的并且传统上被源代码管理忽略 我对工作目录参数感兴趣 我需要它在程序员的机器上保持一致 并且它具有以下价值 outDir而不是默认的 ProjectDir 我怎样才能解决这
  • 为什么从网上下载Git 2.0,总是得到1.9.4的安装包?

    为什么从网上下载Git 2 0 总是得到1 9 4的安装包 为什么你不能在互联网上的任何地方找到一个不仅标记为 2 0 而且你下载的安装存档也标记为这样的 Git 安装程序包 例如 这个2 1 3 站点 http git scm com d
  • 如何在现有裸存储库中创建引用日志信息

    您可能已经知道 默认情况下 git 不会为新的裸存储库启用引用日志更新 问题是 我有一个很长的历史存储库 但它是在我设置 logAllRefUpdates 标志之前创建的 现在我希望其他应用程序可以使用该信息 如何通过对现有存储库进行最少的
  • Git - 使用过滤器分支删除带有空变更集的提交

    如何使用 git filter branch 删除没有变更集的提交 我使用以下方法重写了我的 git 历史记录 git filter branch tree filter rm r f my folder f HEAD 效果很好 但现在我有
  • 使用nodegit切换分支/标签

    我整个早上都在尝试打开现有的存储库并使用 nodegit 更改分支或标签 文档内容很丰富 但似乎已经过时了 关于我做错了什么有什么想法吗 var NodeGit require nodegit var open NodeGit Reposi

随机推荐

  • PYTHON执行DOS命令乱码的问题和解决

    今天想查询一个网站 某些小网站的命名是几个字母 数字 于是想起来了DOS的ping命令 查询字母值 python执行ping命令非常简单 import os os system ping XXXXX 然后很简答 乱码了 由于system只有
  • Python 算数运算符

    视频版教程 Python3零基础7天入门实战视频教程 Python支持所有的基本算术运算符 这些算术运算符用于执行基本的数学运算 如加 减 乘 除和求余等 下面是7个基本的算术运算符 以下 假设变量a为10 变量b为21 实例代码 定义变量
  • 安装vuecli3.0.3指定版本_CASTEP 19.1 linux学术版本安装教程

    1 CASTEP学术免费版本申请 CASTEP Cambridge Sequential Total Energy Package 的缩写 是一个基于密度泛函方法的从头算量子力学程序 典型的应用包括表面化学 键结构 态密度和光学性质等研究
  • 新手学Python开发的三大注意事项

    相信有不少刚刚开始学习Python的吧 前期可能繁琐的代码会让你想放弃这门技术 小编在此给大家列一个顺序 希望能够很好的帮助你坚持下去哦 1 学习目标 2 整体认知 3 学习路线 新手学Python开发的三大注意事项 学习要有目标这样在学习
  • 基础算法:整数二分——数的范围

    题目 给定一个按照升序排列的长度为 n 的整数数组 以及 q 个查询 对于每个查询 返回一个元素 k 的起始位置和终止位置 位置从 0 开始计数 如果数组中不存在该元素 则返回 1 1 输入格式 第一行包含整数 n 和 q 表示数组长度和询
  • 2021年Vue最常见的面试题以及答案(面试必过)

    Vue常见面试题 Vue的优点 说说你对SPA单页面的理解 它的优缺点分别是什么 SPA首屏加载速度慢的怎么解决 Vue初始化过程中 new Vue options 都做了什么 对MVVM的理解 Vue数据双向绑定原理 Vue的响应式原理
  • Java网络编程之带文件名的文件传输(服务器+客户端)

    Java网络编程之带文件名的文件传输 文章总览 作者的话 需求分析 客户端代码 服务器端代码 服务器线程定义 结语 文章总览 作者的话 最近做的某个项目涉及到这方面的内容 因有感写下这篇学习记录 希望能给和我一样正在学习java的朋友们起到
  • 网站云服务器资料本地备份,云服务器上备份本地数据

    云服务器上备份本地数据 内容精选 换一换 云服务器备份 CSBS Cloud Server Backup Service 提供对弹性云服务器 Elastic Cloud Server 和裸金属服务器 Bare Metal Server 的备
  • MySQL的主从模式搭建

    一 安装 MySQL 1 在虚拟机中先装两台 centos7 2 然后分别在两台 cnetos7 中安装 mysql 并配置好 mysql 的相关权限等 3 使用MySQL数据库连接工具 SQLyog 或者 Navicat 测试数据库的连接
  • 谷歌浏览器安卓版_安卓android版Chrome浏览器设置教程

    Google Chrome是一款由Google公司开发的网页浏览器 该浏览器基于其他开源软件撰写 包括WebKit 目标是提升稳定性 速度和安全性 并创造出简单且有效率的使用者界面 软件的名称是来自于称作Chrome的网络浏览器GUI 图形
  • Android集成常见问题

    本文介绍了Android SDK集成过程中可能出现的问题和解决方法 调用实人认证SDK 进入认证页面一直显示转圈加载 查看logcat日志 如果出现ErrorCode 202 则说明签名图片文件 yw 1222 0670 jpg 存在问题
  • 2021-02-28

    simulink控制器封装库 控制器封装库 一 封装库的安装和LADRC模块的使用
  • activiti7-2-流程定义、实例、任务查询、任务处理、压缩部署、定义查询、定义删除、定义资源查询、历史信息查询

    我是一个目录 1 流程定义 1 1 绘制流程图 1 2 简单介绍API和原理机制 1 2 1 API 1 2 2 原理机制 1 3 流程定义部署测试类 1 4 分析影响的表 2 流程实例 2 1 启动流程实例 2 2 分析影响的表 3 任务
  • windows 2003 传真服务器高级配置与管理

    这里我和大家一起来了解一下传真服务器的高级配置与管理 在上一博文中我说了 我们要实现电子邮件的通知和传真服务的控制台管理已经日志分析的功能 首先介绍的是windows 2003自带的传真服务器提供了SMTP支持传真到达通知的功能和传真发送成
  • 备战2024秋招面试题-最左匹配原则、索引失效情况、算法(最长回文子串)

    前言 textcolor Green 前言 前言 快秋招了 那么这个专栏就专门来记录一下 同时呢整理一下常见面试题 部分题目来自自己的面试题 部分题目来自网络整理 给我冲 学习目标 面试题 算法题 完成 学习目标 最左匹配原则 索引失效情况
  • 在微信小程序里面使用npm

    在微信小程序里面使用npm 从小程序基础库版本 2 2 1 或以上 及开发者工具 1 02 1808300 或以上开始 小程序支持使用 npm 安装第三方包 为了扩展微信小程序的功能 现在允许微信小程序使用npm 来扩展我们的功能 使用很简
  • 计算机三级网络技术备考复习资料

    以前用到的资料 偶尔翻翻还挺有用 记录之 第一章 计算机基础 分析 考试形式 选择题和填空题 6个的选择题和2个填空题共10分 都是基本概念 1 计算机的四特点 有信息处理的特性 有广泛适应的特性 有灵活选择的特性 有正确应用的特性 此条不
  • vue 测试环境 生产环境 线上环境 环境配置

    var env config dev name dev api url location protocol 10 0 0 230 80 api server url location protocol narcissus ih2ome cn
  • cpp 5.7

    5 7 include
  • 谈谈 Docker Volume 之权限管理(一)

    Volume数据卷是Docker的一个重要概念 数据卷是可供一个或多个容器使用的特殊目录 可以为容器应用存储提供有价值的特性 持久化数据与容器的生命周期解耦 在容器删除之后数据卷中的内容可以保持 Docker 1 9之后引进的named v