一 创作背景
再复制Docker影像文件或访问Docker容器内已安装卷上的文件时我们常常会遇到:“权限被拒绝”的错误,在此,您将了解到为什么会出现“权限被拒绝”的错误以及如何解决这个问题。
二 目的
在深入探讨 Docker 容器中的 Permission Denied问题之前,最好了解 Linux 中权限的基本知识。如果您已经熟悉这些概念,则可以跳过本段。可以在 Ubuntu 文档和这个关于umask的优秀解释 中找到熟悉权限的一个很好的起点,如果您想要快速总结,请继续。
三 简介
我们创建一个目录
mkdir publish_test
我们查看一下该文件的权限
ls -la
输出内容如下
drwxrwxrwx 3 root root 4096 Dec 20 16:23 publish_2023
让我们从左往右检查一下这里列出的项目
d | 表示这是一个目录 |
rwx | 所有者的权限,在这种情况下,所有者具有读取、写入和执行权限。 |
rwx | 组的权限。用户属于一个或多个组。在这种情况下,权限与所有者的权限相同。 |
rwx | 其他人的权限:在这种情况下,任何其他人,无论是所有者还是不属于该组,都将具有读取、写入和 执行权限。 |
root | 该目录由该用户所有。在后台,这个逻辑名称被映射到一个用户id(uid)。当您只有一个用户时。这可能是uid1000 |
root | 该目录由该组所有。在后台,这个逻辑名称被映射到一个组id(gid)。你的gid可能是1000。 |
ok,我们继续创建一个txt文件,然后我们查看该文件拥有的权限。
进入该目录
cd /usr/local/publish_test
创建文件defaultfilepermissions.txt,并查看文件权限
touch defaultfilepermissions.txt
ls -la
输出内容如下:
drwxr-xr-x 2 root root 4096 Dec 21 11:10 .
drwxr-xr-x. 22 root root 4096 Dec 21 10:56 ..
-rw-r--r-- 1 root root 0 Dec 21 11:10 defaultfilepermissions.txt
权限的列出方式与目录类似。没有 d 第一项,因为它当然不是目录,并且文件没有任何执行权限
三 先决条件
安装docker
查看用户组
四 以Root身份运行容器
我们在/usr/local/publish_test目录下创建一个Dockerfile,DockerFile的内容如下:
FROM alpine:3.16.2
COPY defaultfilepermissions.txt /tmp/defaultfilepermissions.txt
该 FROM指令将使用 Alpine Linux 3.16.2 基础 Docker 映像,并且该 COPY指令会将本地defaultfilepermissions.txt文件复制到位于 location 的 Docker 映像中 /tmp/defaultfilepermissions.txt。
构建Docker映像
cd /usr/local/publish_test
sudo docker build -f Dockerfile -t dockertest .
输出内容如下:
然后我们以交互模式启动Docker容器,以方便我们能够继续使用shell
sudo docker run --name dockercontainer --rm -it dockertest /bin/sh
输出内容如下
[root@iZ2ze6on3jy8afby5yaj0bZ publish_test]# sudo docker run --name dockercontainer --rm -it dockertest /bin/sh
/ #
进入tmp目录
cd tmp
查看tmp目录中的文件
ls
尝试执行cat defaultfilepermissions.txt,查看输出内容
cat defaultfilepermissions.txt
我们可以看到我们文件的内容
然后我们使用vi命令,发现文件也是可以被编辑的。这些结果都是合乎逻辑的,root用户执行它们,root可以做任何事情。
键入 exit ,退出shell
我们删除Docker映像
sudo docker rmi dockertest
五 以用户1000运行容器
此测试与第一个测试类似,不同之处在于您将为Docker容器创建一个用户,这样,容器将不再以root身份用户运行,这是一种更安全的容器运行方式。
还是在该目录下(/usr/local/publish_test),我们修改Dockerfile。
内容如下:
FROM alpine:3.16.2
RUN addgroup --g 1000 groupcontainer
RUN adduser -u 1000 -G groupcontainer -h /home/containeruser -D containeruserUSER containeruser
COPY defaultfilepermissions.txt /tmp/defaultfilepermissions.txt
该dockerfile的解释如下:
使用 gid 1000 创建RUN addgroup一个组,
groupcontainer,使用 RUN adduser,containeruser创建一个 uid 为 1000 的用户 属于组 groupcontainer和主目录 /home/containeruser
USER containeruser,容器与用户一起运行 containeruser;
本地 defaultfilepermissions.txt文件被复制到 containeruser.
我们继续使用之前的命令,构建并运行容器
sudo docker build -f Dockerfile -t dockertest .
输出内容如下:
继续用 交互模式启动Docker容器,以方便我们能够继续使用shell
sudo docker run --name dockercontainer --rm -it dockertest /bin/sh
/ $ cd tmp
/tmp $ ls
defaultfilepermissions.txt
/tmp $ cat defaultfilepermissions.txt
11111111111111111111111111111111111111111111111111111111111111111111111/tmp $
尝试执行 cat test.txt,你会注意到文件的内容被输出了。可以这样做,因为 other具有读取权限。请记住,容器 containeruser现在以用户身份运行。
我们尝试用vi去编辑并且保存文件,这是不可能的:会发出警告,指出该文件是只读的。那是因为 other没有写权限。
ps:
- 你可以使用 vi 编辑器来编辑文件。 运行以下命令: vi /path/to/file ...
- 在 vi 编辑器中,按下 i 进入插入模式,然后进行编辑。 完成后,按下 Esc 键退出插入模式。
- 要保存文件并退出 vi 编辑器,请输入以下命令: :wq 这将保存文件并退出编辑器。
- 退出容器的交互式模式,请输入以下命令: exit
删除Docker映像
sudo docker rmi dockertest
六 以用户1024运行容器并更改所有权
您将解决权限问题,诀窍是将文件的所有权更改为运行 Docker 容器的用户。创建一个目录4-containeruser1024changedowner。是Dockerfile:
FROM alpine:3.16.2
RUN addgroup --g 1024 groupcontainer
RUN adduser -u 1024 -G groupcontainer -h /home/containeruser -D containeruser
USER containeruser
COPY --chown=containeruser:groupcontainer defaultfilepermissions.txt /home/containeruser/defaultfilepermissions.txt
我们可以看到在Copy行,文件的所有权 test.txt更改为用户 containeruser和组 groupcontainer。
像以前一样构建并运行容器。导航到用户的主目录containeruser并列出文件
尝试执行 cat test.txt,你会注意到文件的内容被输出了。
尝试编辑文件 vi并保存文件。这是允许的,因为这一次, containeruser拥有该文件并具有适当的写入权限。
删除Docker 映像