【问题标题】:Dotnet build permission denied in Docker container running Jenkins运行 Jenkins 的 Docker 容器中的 Dotnet 构建权限被拒绝
【发布时间】:2018-11-30 11:25:57
【问题描述】:

我正在尝试使用 Jenkins 构建一个 .NET 应用程序。 Jenkins 实例在 Docker 容器中运行。

我的Jenkinsfile如下:

pipeline {
  agent {
    docker {
      image 'microsoft/dotnet:2.1-sdk'
      registryUrl 'https://index.docker.io/v1/'
    }
  }
  stages {
    stage('Build') {
      steps {
        sh 'dotnet build MyApplication/Application.csproj -c Release -o /app'
      }
    }
    stage('Test') {
      steps {
        sh 'dotnet test MyApplication/Application.csproj -c Release -r /results'
      }
    }
  }
}

当我尝试构建时,我在 Jenkins 构建输出中看到以下错误:

System.UnauthorizedAccessException: Access to the path '/.dotnet' is denied. ---> System.IO.IOException: Permission denied
   --- End of inner exception stack trace ---
   at System.IO.FileSystem.CreateDirectory(String fullPath)
   at System.IO.Directory.CreateDirectory(String path)
   at Microsoft.Extensions.EnvironmentAbstractions.DirectoryWrapper.CreateDirectory(String path)
   at Microsoft.DotNet.Configurer.FileSentinel.Create()
   at Microsoft.DotNet.Configurer.DotnetFirstTimeUseConfigurer.Configure()
   at Microsoft.DotNet.Cli.Program.ConfigureDotNetForFirstTimeUse(INuGetCacheSentinel nugetCacheSentinel, IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel, IAspNetCertificateSentinel aspNetCertificateSentinel, IFileSentinel toolPathSentinel, Boolean hasSuperUserAccess, DotnetFirstRunConfiguration dotnetFirstRunConfiguration, IEnvironmentProvider environmentProvider)
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, ITelemetry telemetryClient)
   at Microsoft.DotNet.Cli.Program.Main(String[] args)

“.dotnet”文件夹似乎在 Docker 容器中受到保护。有没有办法获得读/写权限,或者改变它的位置?当我 bash 进入容器时,我似乎找不到该文件夹​​。

感谢您的帮助。

【问题讨论】:

    标签: .net docker jenkins asp.net-core build


    【解决方案1】:

    您可以按照@colmulhall 的建议设置HOME 环境变量,但随后您会将docker 容器主目录设置为/tmp

    "dotnet"的方式设置环境变量DOTNET_CLI_HOME:

    environment {
        DOTNET_CLI_HOME = "/tmp/DOTNET_CLI_HOME"
    }
    

    或者在调用dotnet之前运行:

    export DOTNET_CLI_HOME="/tmp/DOTNET_CLI_HOME"
    


    更新

    取自https://www.jenkins.io/doc/pipeline/tour/environment/的示例 Jenkins 管道代码

    看看DOTNET_CLI_HOME是如何在environment部分定义的:

    pipeline {
        agent {
            label '!windows'
        }
    
        environment {
            DISABLE_AUTH = 'true'
            DB_ENGINE    = 'sqlite'
            DOTNET_CLI_HOME = "/tmp/DOTNET_CLI_HOME"
        }
    
        stages {
            stage('Build') {
                steps {
                    echo "Database engine is ${DB_ENGINE}"
                    echo "DISABLE_AUTH is ${DISABLE_AUTH}"
                    sh 'printenv'
                }
            }
        }
    }
    

    有很多方法可以实现这一点。如果您使用的是 docker,也许更好的方法是在 docker 镜像中定义环境变量 DOTNET_CLI_HOME

    【讨论】:

    • 这段代码需要在哪里写environment {..
    • @ArvindChourasiya 如果您使用 Jenkins,请查看此内容以了解如何在 jenkins 管道阶段定义环境变量:jenkins.io/doc/pipeline/tour/environment
    【解决方案2】:

    该问题似乎与尝试将数据写入 Docker 容器的顶层 ('/') 有关。

    将以下内容添加到 Jenkinsfile 可确保设置主目录,并且可以在具有正确权限的位置创建 .dotnet 文件夹。

    environment {
       HOME = '/tmp'
    } 
    

    【讨论】:

    • 这解决了问题,但如果其他脚本依赖 home 位于其他地方,或者如果您在 Dockerfile 中设置了 USER 存在引导问题,则不是一个好主意。设置在~/.blah 中,突然HOME 设置为不同的位置/tmp
    【解决方案3】:

    自定义 Docker 镜像,对 Jenkinsfile 的改动最小

    如果你有以下条件,这个选项很好。

    1. 您有多个 Jenkinsfile 项目都使用同一个 docker 映像。
    2. 您有自定义 Nuget 包源。

    如果您使用的是基于 dotnet sdk docker 镜像的自定义 docker 镜像。您可以使用以下内容创建 Docker 文件。

    FROM mcr.microsoft.com/dotnet/core/sdk:2.2
    WORKDIR /
    
    # Setup default nuget.config, useful for custom nuget servers/sources
    # Set Project-specific NuGet.Config files located in any folder from the solution folder up to the drive root. These allow control over settings as they apply to a project or a group of projects.
    COPY nuget.config .
    
    # Set the Environment Variable for the DOTNET CLI HOME PATH
    ARG dotnet_cli_home_arg=/tmp/
    ENV DOTNET_CLI_HOME=$dotnet_cli_home_arg
    

    在与 docker 文件相同的目录中创建映像。

    docker build -t jenkins-dotnet:latest .
    

    为要推送到的服务器设置标签。

    docker tag jenkins-dotnet:latest some.docker.registry/jenkins-dotnet
    

    将您的 jenkins-dotnet 图片推送到

    docker push some.docker.registry/jenkins-dotnet
    

    那么您所有项目的 Jenkinsfile 可能如下所示。

    pipeline {
      agent {
        docker {
          image 'some.docker.registry/jenkins-dotnet'
          registryUrl 'https://some.docker.registry'
        }
      }
      stages {
        stage('Build') {
          steps {
            sh 'dotnet build MyApplication/Application.csproj -c Release -o /app'
          }
        }
        stage('Test') {
          steps {
            sh 'dotnet test MyApplication/Application.csproj -c Release -r /results'
          }
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-01-06
      • 2018-04-23
      • 1970-01-01
      • 2021-11-02
      • 1970-01-01
      • 2021-02-02
      • 1970-01-01
      • 2019-11-01
      • 2022-01-12
      相关资源
      最近更新 更多