Jenkins流水线执行失败后如何清理Docker挂载产生的root属主工作区残留文件
根因分析
- 你将宿主机
./deploy目录挂载到了容器的/var/www/html路径,容器内以root身份运行的Web进程写入的文件,在宿主机上的属主就是uid为0的root,默认Jenkins用户没有权限修改/删除这类文件 - 之前的
docker exec清理逻辑存在路径错误:容器内/var/www/html对应宿主机的./deploy,你执行删除/var/www/html/deploy属于路径不存在,自然无法生效 - 你之前的执行顺序错误:先删本地目录再销毁容器,容器还在运行时挂载的文件被锁,也会导致删除失败
可行解决方案
方案1:修正清理逻辑(无需修改原有容器配置,推荐)
调整post阶段执行顺序,先通过容器删除挂载目录内的所有文件,再销毁容器,最后清理本地残留目录:
post { always { // 先保证容器处于运行状态才能exec,执行失败也继续往下走 sh "docker start ${DB_CONTAINER_NAME} || true" // 直接删除容器内/var/www/html下的所有内容,对应宿主机./deploy的全部文件 sh "docker exec -u root ${DB_CONTAINER_NAME} rm -rf /var/www/html/* /var/www/html/.* || true" // 再销毁容器 sh "docker stop ${DB_CONTAINER_NAME} || true && docker rm ${DB_CONTAINER_NAME} || true;" // 最后删除本地空目录,此时无root文件残留,Jenkins有权限操作 sh "rm -rf `pwd`/deploy || true" } }
如果原容器已经崩溃无法启动,可以启动临时容器挂载目录完成清理:
sh "docker run --rm -v `pwd`/deploy:/clean:Z alpine rm -rf /clean/* /clean/.*"
方案2:从根源避免root文件生成(长期方案)
启动容器时指定运行用户和Jenkins用户的uid/gid一致,容器内写入的文件自动归属Jenkins用户,后续无需特殊清理:
sh "docker create -P --user $(id -u):$(id -g) --name=${DB_CONTAINER_NAME} -v `pwd`/deploy:/var/www/html:Z llnl-lamp:latest"
注意如果容器内的Web服务需要绑定80等特权端口,需要额外添加--cap-add NET_BIND_SERVICE参数,避免无权限启动。
方案3:配置Jenkins sudo权限(不推荐,存在安全风险)
给Jenkins用户配置无密码执行rm命令的权限,直接用sudo删除残留文件:
- 编辑sudoers文件:
visudo - 添加一行:
jenkins ALL=(ALL) NOPASSWD: /usr/bin/rm -rf */deploy - 清理命令改为:
sh "sudo rm -rfpwd/deploy"
内容的提问来源于stack exchange,提问作者shelane
相关产品推荐
相关产品推荐

