Docker run 容器使用-v挂载目录总会启动失败的解决方案

问题:docker run一个容器,并且挂载了目录;但是总是启动失败【docker ps 后发现没有启动】

[root@localhost tomcat]# docker run -d -p 9090:8080 -v /home/dockerfile/tomcat/test:/usr/local/apache-tomcat-8.5.61/webapps/test -v /home/dockerfile/tomcat/logs/:/usr/local/apache-tomcat-8.5.61/logs --name yjytomcat diytomcat
b13fc0b57b9fc17019bc8119cb572677889d663f24813150506f381842066c2d
[root@localhost tomcat]# docker ps
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS              PORTS                    NAMES
2c245c597ae4        portainer/portainer   "/portainer"        2 days ago          Up 6 hours          0.0.0.0:8088->9000/tcp   optimistic_lamport


原因: CentOS7中的安全模块selinux把权限禁掉了,无法使用-v命令进行挂载
解决方案: 添加selinux规则,将要挂载的目录添加到白名单

[root@localhost tomcat]# chcon -Rt svirt_sandbox_file_t /home/dockerfile/tomcat/test
[root@localhost tomcat]# chcon -Rt svirt_sandbox_file_t /home/dockerfile/tomcat/logs


再重新创建容器即可。

转载:https://blog.youkuaiyun.com/qq_40569835/article/details/112854523

<think>我们在处理用户问题时,首先明确用户需求:普通用户运行Docker容器时,使用`-v`挂载主机目录,导致挂载出来的目录在主机上属于root用户,普通用户无法访问。引用中提供了部分信息:引用[1]提到使用非root用户操作docker,可以通过sudo方式操作docker,但用户可能不希望使用sudo,因为使用sudo仍然会以root权限操作,挂载目录可能还是root权限。引用[2]提到设置root用户和密码的环境变量,但这不是当前问题。引用[3]提到权限错误问题,并建议确保媒体库的根文件夹及其所有文件和子文件夹对其他用户可读和可搜索,即通过`chmod`改变权限。引用[4]是拉取和启动alpine镜像的示例。用户的问题核心在于:容器内进程以什么用户运行,会影响到挂载卷的文件权限。容器内默认以root用户运行,所以挂载到主机上的文件目录会属于root用户,导致普通用户无法访问。解决方案通常有以下几种:1.在容器使用与主机普通用户相同的UID和GID运行进程,这样挂载出来的文件权限就与主机普通用户一致。2.在容器启动后,通过`chmod`或`chown`更改挂载目录的权限(但注意,这可能会改变主机上的文件权限,需要谨慎)。3.使用Docker的“用户命名空间”功能(usernamespaces),将容器内的root用户映射到主机上的普通用户。根据问题,我们推荐第一种方法,即指定容器内运行进程的用户UID和GID。具体步骤:1.获取主机普通用户的UID和GID(假设用户名为`appman`):`id-u`获取UID,`id-g`获取GID。2.在运行容器时,通过`-u`选项指定用户,例如:`dockerrun-u$(id-u):$(id-g)...`3.但注意,容器内的用户可能不存在于容器的/etc/passwd中,这可能导致一些权限问题,比如运行某些命令时显示“Ihavenoname!”等。为了避免这种情况,我们可以:-挂载主机的/etc/passwd和/etc/group文件(但要注意这可能会带来安全问题,因为容器内的用户将拥有主机上相同UID用户的权限):`-v/etc/passwd:/etc/passwd:ro-v/etc/group:/etc/group:ro`-或者,在容器内创建相应的用户(需要构建自定义镜像)。4.另外,对于挂载目录,如果容器内需要写入,则主机上该目录需要提前设置好权限,使得该UID和GID的用户有权限写入。如果目录已经存在并且属于root,可以先通过`chown`改变所有权,或者在运行容器前先创建好目录并设置合适的权限。5.如果用户希望在容器使用特定用户(如appman),可以在Dockerfile中创建该用户(指定UID和GID),然后在运行容器使用该用户。6.如果用户不想使用`-u`指定用户,也可以使用sudo来挂载,但这会导致挂载目录权限为root,所以还是推荐使用`-u`。举例:假设主机普通用户的UID为1000,GID为1000,我们要运行一个alpine容器,并挂载当前目录下的`data`目录容器的`/data`:```bashdockerrun-it--rm\-u1000:1000\-v"$(pwd)"/data:/data\alpine:3.16\/bin/sh```这样,在容器内创建的文件在主机上就会属于UID为1000的用户。但是,如果主机上被挂载目录(比如`data`)原本属于root,那么容器启动后,容器内的进程虽然以UID1000运行,但可能没有权限写入该目录(如果主机目录权限不允许其他用户写入)。因此,在运行容器之前,需要确保主机上被挂载目录对UID1000的用户有写入权限。可以使用:```bashmkdirdatachown1000:1000data#或者设置权限为777(不推荐,因为太开放)chmod777data#或者更安全的是chmod770,然后确保目录的组是1000并且用户属于该组```注意:在`dockerrun`命令中,`-u`选项指定的用户权限会受到主机目录权限的限制,因此主机目录的权限设置同样重要。另外,引用[1]中提到了使用sudo操作docker,这实际上是以root用户运行docker容器,所以挂载目录仍然是root权限。所以,我们应该避免使用sudo来运行容器(除非必要),而是将普通用户加入docker用户组(然后重新登录),使该用户可以直接运行docker命令(不通过sudo)。这样,我们就可以在运行容器时通过`-u`指定用户,而主机上由该容器进程创建的文件权限将由`-u`指定的用户决定。但是,将用户加入docker组意味着该用户拥有了直接管理docker的权限(等同于root权限),因为docker守护进程是以root身份运行的。这存在安全风险,所以需要谨慎。因此,如果安全要求高,可以考虑使用第二种方法:用户命名空间(usernamespaces)。需要配置docker守护进程启用用户命名空间。但这种方法需要重新配置docker,且会影响所有容器。总结:推荐使用`-u`指定容器内进程的UID和GID,同时确保主机上挂载目录对该UID有适当的权限。下面给出一个完整的示例:假设我们使用普通用户`appman`(UID=1000,GID=1000)来运行容器,并挂载主机上的`/path/to/host/data`到容器的`/data`。步骤1:创建主机目录并设置权限(如果目录不存在)```bashmkdir-p/path/to/host/datachown1000:1000/path/to/host/data```步骤2:运行容器```bashdockerrun-it--rm\-u1000:1000\-v/path/to/host/data:/data\alpine:3.16\sh-c"echo'hellofromcontainer'>/data/test.txt"```运行后,在主机上查看`/path/to/host/data/test.txt`,应该属于UID1000的用户。注意:如果容器内需要使用的用户UID在容器的/etc/passwd中不存在,则可能会出现如`Ihavenoname!`的提示(在shell的提示符处),但这通常不影响文件操作。如果需要在容器使用用户名,则需要在构建镜像时创建该用户。例如,构建自定义镜像的Dockerfile:```DockerfileFROMalpine:3.16RUNaddgroup-g1000appman&&adduser-u1000-Gappman-DappmanUSERappman```然后运行容器时,就不需要指定`-u`(因为Dockerfile中已经指定了USER),且容器内的进程以appman用户运行,挂载目录也会属于主机上的UID1000。因此,解决权限问题的核心在于:让容器内的进程以主机上普通用户的UID和GID运行,并确保主机上挂载目录对该UID具有所需的权限。相关问题:1.如何避免容器内的root用户在主机上创建的文件属主为root?2.使用用户命名空间(usernamespaces)配置docker守护进程的步骤?3.如何通过Dockerfile创建指定UID/GID的用户?4.如何安全地让普通用户使用docker命令而不用sudo?我们将按照上述总结和示例来回答用户。</think> ### 解决 Docker 挂载目录权限问题(普通用户运行,root 属主问题) 当普通用户使用 `docker run -v` 挂载目录时,容器内默认以 root 用户运行,导致挂载到主机上的目录权限归属 root。以下是完整解决方案--- #### 解决方案 1:挂载时指定用户 UID/GID(推荐) ```bash # 获取当前用户的 UID 和 GID USER_ID=$(id -u) GROUP_ID=$(id -g) # 运行容器时同步用户权限 docker run -it --rm \ -u $USER_ID:$GROUP_ID \ # 关键!指定容器内用户ID -v /host/path:/container/path \ # 挂载目录 your-image:tag ``` **原理**:通过 `-u` 参数强制容器进程使用与宿主相同的 UID/GID,使生成文件权限一致[^3]。 --- #### 解决方案 2:预配置目录权限 ```bash # 1. 创建目录并设置权限 sudo mkdir -p /data/mounted_dir sudo chown -R $USER:$USER /data/mounted_dir # 确保属主是当前用户 sudo chmod -R 775 /data/mounted_dir # 保证组读写权限 # 2. 挂载目录 docker run -v /data/mounted_dir:/app/data your-image ``` --- #### 解决方案 3:创建同名用户并指定权限(需自定义镜像) ```dockerfile # Dockerfile 示例 FROM alpine:3.16 # 创建与宿主相同 UID/GID 的用户 RUN addgroup -g 1000 appuser && \ adduser -u 1000 -G appuser -D appuser USER appuser # 切换用户 ENTRYPOINT ["/bin/sh"] ``` **运行命令**: ```bash docker build -t custom-image . docker run -v /host/path:/data -it custom-image ``` > **关键说明**: > 1. `-u $(id -u):$(id -g)` 是最直接的解决方案[^1][^3] > 2. 当挂载现有目录时,必须确保宿主目录可写:`chown -R user:group /path`[^3] > 3. 安全警告:避免使用 `chmod 777`,优先使用精确的权限控制 --- ### 验证步骤 ```bash # 在容器内创建测试文件 docker run -u $(id -u) -v $PWD/data:/data alpine touch /data/test.txt # 检查宿主文件权限 ls -l $PWD/data/test.txt # 应显示当前用户而非 root ``` 通过上述方法,可彻底解决挂载目录的 root 属主问题,保证普通用户正常访问[^1][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值