Jenkins错误的卷权限

31

我有一台托管Oracle Linux的虚拟机,我已经安装了Docker并使用docker-compose文件创建了容器。我将jenkins卷放置在一个共享文件夹下,但是当启动docker-compose时,我为Jenkins获得了以下错误:

jenkins | touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied jenkins | Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions? jenkins exited with code 1

这里是卷的声明

  volumes:
    - "/media/sf_devops-workspaces/dev-tools/continuous-integration/jenkins:/var/jenkins_home"

我有同样的问题,有人可以帮助我们吗? - Abderrahim
请放置您的完整docker-compose.yml文件。 - OscarAkaElvis
快速解决方案:查找在容器内运行Jenkins的用户的数字用户ID,并将主机目录的所有者更改为此用户ID。 - Henry
一些更多的想法:https://dev59.com/FmAg5IYBdhLWcg3wfa96#27021154 - Henry
@OscarAkaElvis https://hastebin.com/bucunekelo。 - Taoufik J
@Henry,我该怎么做?我没有使用Dockerfile,只有一个Docker Compose!但是容器无法启动,因此我无法访问它并执行命令。 - Taoufik J
13个回答

31
使用-u参数是一个简单的解决方法。请注意,这将作为root用户(uid = 0)运行。
docker run -u 0 -d -p 8080:8080 -p 50000:50000 -v /data/jenkins:/var/jenkins_home jenkins/jenkins:lts

20

正如 haschibaschi 所说,您在容器中的用户具有不同的 userid:groupid 与主机上的用户。

解决这个问题的方法是在不使用(有问题的)卷映射的情况下启动容器,然后在容器上运行 bash:

docker run -p 8080:8080 -p 50000:50000 -it jenkins bin/bash

进入容器的 shell 后,运行 id 命令,你会得到如下结果:

uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)

退出容器,前往您尝试映射的文件夹并运行:

chown -R 1000:1000 .

现在权限已经匹配,您应该能够使用卷映射运行原始的docker命令。


1
如何在Windows中实现这个? - Vikash
在Mac上也不起作用。这在Alpine Linux主机上运行得非常出色,然而在Mac M1上却没有完全成功。我不得不使用chmod 777(不是最好的方式)才能让它正常工作。 - undefined

16

问题是,容器中的用户具有与主机上的用户不同的userid:groupid。

您有两种选择:

  1. 您可以确保容器中的用户具有与可以访问挂载卷的主机上的用户相同的userid:groupid。为此,您需要在Dockerfile中调整用户。使用相同的userid:groupid创建一个用户,然后切换到该用户 https://docs.docker.com/engine/reference/builder/#user

  2. 您可以确保主机上的用户具有与容器中的用户相同的userid:groupid。为此,使用 docker exec -it <container-name> bash 进入容器,并显示用户ID id -u <username> 组ID id -G <username>。将挂载卷的权限更改为此userid:groupid。


1
我无法启动容器,因此无法访问它并执行第二个解决方案... 对于第一个解决方案,您能否添加一些详细信息? - Taoufik J
对于第一种解决方案,您需要构建Docker镜像。这意味着您需要Dockerfile和复制到Dockerfile中的工件。如果您拥有这些内容,您可以构建镜像并更改Dockerfile。 - haschibaschi
@TaoufikJabbari 为什么你无法启动容器?实际上,你只需要镜像,即使在另一台机器上也可以启动它。你可以使用其他启动命令,只要镜像中有 bash 就可以工作。 - Henry
@Henry 我有点搞不明白,镜像是类,而实例就相当于容器吗?因为如果我运行一个新的容器,它不会影响在compose中定义的那个,因为它们是两个不同的实例.. - Taoufik J
@TaoufikJabbari 不,那是正确的,但是只要找到数字用户ID,您就不需要完全相同的容器(这是“类信息”)。 - Henry

2
你可能正在使用 SELinux。对我而言,以特权模式运行容器解决了问题:
sudo docker run --privileged -p 8080:8080 -p 50000:50000 -v /data/jenkins:/var/jenkins_home jenkins/jenkins:lts
来自https://docs.docker.com/engine/reference/commandline/run/#full-container-capabilities---privileged
引用: --privileged标志赋予容器所有权限,并且它还解除了设备cgroup控制器强制执行的所有限制。换句话说,容器几乎可以做主机能做的所有事情。该标志存在是为了允许特殊用例,比如在Docker中运行Docker。

在 RHEL 7.9 上工作过。 - Hussein Hijazi

1
作为 @Kiem 回答的更新,使用 $UID 确保容器使用与主机相同的用户 ID,你可以这样做:
docker run -u $UID -d -p 8080:8080 -p 50000:50000 -v /data/jenkins:/var/jenkins_home jenkins/jenkins:lts

你实际使用过这个解决方案吗?我在 Jenkins 中尝试了一下,但是出现了以下错误:groovy.lang.MissingPropertyException: No such property: UID for class: groovy.lang.Binding - Cruncher

1
我之前在使用Minikube/Kubernetes时也遇到了类似的问题。
securityContext:
  fsGroup: 1000
  runAsUser: 0

正在部署 -> 规范 -> 模板 -> 规范


1
我通过更新权限来修复了它。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: devops-tools
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins-server
  template:
    metadata:
      labels:
        app: jenkins-server
    spec:
      **securityContext:
            fsGroup: 1000
            runAsUser: 0****
      serviceAccountName: jenkins-admin
      containers:
        - name: jenkins
          image: jenkins/jenkins:lts
          resources:
            limits:
              memory: "2Gi"
              cpu: "1000m"
            requests:
              memory: "500Mi"
              cpu: "500m"
          ports:
            - name: httpport
              containerPort: 8080
            - name: jnlpport
              containerPort: 50000
          livenessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 90
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          volumeMounts:
            - name: jenkins-data
              mountPath: /var/jenkins_home
      volumes:
        - name: jenkins-data
          persistentVolumeClaim:
              claimName: jenkins-pv-claim

请不要将“谢谢”作为答案。一旦您拥有足够的声望,您将能够投票支持有帮助的问题和答案。- 来自审核 - undefined

0

使用此命令

$ chmod +757 /home/your-user/your-jenkins-data

虽然此代码可能回答了问题,但提供关于为什么和/或如何回答该问题的附加上下文可以提高其长期价值。 - dan1st

0

在 MacOS 上遇到了类似的问题,在 Minikube/Kubenetes 上使用 helm 安装了 Jenkins,经过多次尝试后,我在用于部署 Jenkins 的 values.yaml 中添加了 runAsUser: 0(作为 root 用户),最终解决了该问题。

master:
  usePodSecurityContext: true
  runAsUser: 0
  fsGroup: 0

只要小心,因为这意味着您将以 root 身份运行所有命令。


这可能是解决方案的开端。您能否创建一个与主机上用户具有相同UID和GID的用户,并作为该用户运行?我不能赞同以root身份运行的建议,但它似乎确实朝着正确的方向前进。 - dotancohen
是的,您可以使用任何用户。 - luisZavaleta

0

使用 docker-compose.yml 是很不错的选择。

初始设置应该如下所示,给出 priviledged:trueuser:root

version: '3'
services:
  jenkins:
    container_name: jenkins
    image: jenkins/jenkins:lts
    ports:
      - "8080:8080"
      - "50000:50000"
    privileged: true
    user: root
    volumes:
      - ./jenkins_home:/var/jenkins_home
    restart: always

然后,您可以通过运行“docker-compose up -d”成功启动Jenkins容器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接