Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-51462

archiveArtifacts and fileExists inconsistent in docker.inside() closure

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • docker-workflow-plugin
    • None
    • Jenkins 2.112
      Docker Pipeline 1.15, 1.17

      The following Pipeline code produces an error:

      def image = docker.image("any_existing_image_eg_alpine")
      image.inside {
          sh 'date > /tmp/test.txt'
          sh 'cat /tmp/test.txt' //works, shows file
      
          def fileContents = readFile '/tmp/test.txt' //works
          echo "Contents: ${fileContents}" //works, shows file
      
          echo "Exists: ${fileExists('/tmp/test.txt')}" //FAILS (returns false)
          archiveArtifacts '/tmp/*.txt' //FAILS the build
      }
      

      archiveArtifacts always reports that it matched no files (except in $WORKSPACE, see below).

      DSL steps in docker summary (what I've tried):

      • readFile(): works correctly on files in or out of $WORKSPACE
      • writeFile(): works correctly on files in or out of $WORKSPACE
      • fileExists(): works correctly only on files in $WORKSPACE (auto-mounted volume)
      • archiveArtifacts(): archives only files in $WORKSPACE  (auto-mounted volume) 

      So I guess there is a pattern ... and yet the behavior is inconsistent.  I could not find any documentation that explains what the rules are.

      UPDATE: readFile() now throws NoSuchFileException (docker-pipeline 1.17 and pipeline-basic-steps 2.7) for files outside the workspace, which is probably better.

       

       

          [JENKINS-51462] archiveArtifacts and fileExists inconsistent in docker.inside() closure

          Alexander Komarov added a comment - - edited

          Workaround is to first copy the necessary files to the $WORKSPACE that is automatically mounted in the container, or to just do everything in the mounted directory in the first place.

           

          Alexander Komarov added a comment - - edited Workaround is to first copy the necessary files to the $WORKSPACE that is automatically mounted in the container, or to just do everything in the mounted directory in the first place.  

          Khalil Jiries added a comment -

          akom the workaround didn't work for me.

           

          17:58:07 + cp -rf docker-compose-data/clairctl-reports /var/lib/jenkins/workspace/testing/clairctl-reports

          [Pipeline] step 17:58:07 Archiving artifacts 17:58:07 ERROR: No artifacts found that match the file pattern "/var/lib/jenkins/workspace/testing/clairctl-reports/*". Configuration error? *17:58:07 ERROR: ‘/var/lib/jenkins/workspace/testing/clairctl-reports/*’ doesn’t match anything, but ‘*’ does. Perhaps that’s what you mean?

          Khalil Jiries added a comment - akom the workaround didn't work for me.   17:58:07 + cp -rf docker-compose-data/clairctl-reports /var/lib/jenkins/workspace/testing/clairctl-reports [Pipeline] step 17:58:07 Archiving artifacts 17:58:07 ERROR: No artifacts found that match the file pattern "/var/lib/jenkins/workspace/testing/clairctl-reports/* ". Configuration error? *17:58:07 ERROR: ‘/var/lib/jenkins/workspace/testing/clairctl-reports/* ’ doesn’t match anything, but ‘ *’ does. Perhaps that’s what you mean?

          khalilj, I'm not sure what you're doing (you only included the output), but this works fine (I just checked):

          def image = docker.image("alpine")
           image.inside { 
             sh 'date > /tmp/test.txt'
             sh "cp /tmp/test.txt ${WORKSPACE}"
             archiveArtifacts 'test.txt'
           }

          Alexander Komarov added a comment - khalilj , I'm not sure what you're doing (you only included the output), but this works fine (I just checked): def image = docker.image( "alpine" ) image.inside {    sh 'date > /tmp/test.txt'    sh "cp /tmp/test.txt ${WORKSPACE}"    archiveArtifacts 'test.txt' }

          Gabriel Nützi added a comment - - edited

          `writeFile` has the same issue, that it does not write the file to `

          /tmp/test.txt

          ` but I guess instead to `

          $WORKSPACE/tmp/test.txt

          ` which is utterly stupid..., at least it does not work

          Gabriel Nützi added a comment - - edited `writeFile` has the same issue, that it does not write the file to ` /tmp/test.txt ` but I guess instead to ` $WORKSPACE/tmp/test.txt ` which is utterly stupid..., at least it does not work

          Jan Gałda added a comment -

          I guess the `fileExists` checks file presence on host, not inside container. 

          It works for workspace because it is present from both host and running container (automounted)

           

          See following example:

           

          stage('Test') {
              node('yourLabel') {
                  sh('date > /tmp/file_on_host')
                  println("File on host, run from host: ${fileExists('/tmp/file_on_host')}") // true
                  docker.image("ubuntu:latest").inside() {
                      sh('date > /tmp/file_in_docker')
                      println("File on host, run from docker: ${fileExists('/tmp/file_on_host')}") // true
                      println("File in docker, run from docker: ${fileExists('/tmp/file_in_docker')}") // false
                  }
              }
          } 

           

           

          To check presence of file inside docker container, you can use something like:

          boolean isPresent = sh(script: "test -f ${filePath}", returnStatus: true) == 0 

          Jan Gałda added a comment - I guess the `fileExists` checks file presence on host, not inside container.  It works for workspace because it is present from both host and running container (automounted)   See following example:   stage( 'Test' ) {     node( 'yourLabel' ) {         sh( 'date > /tmp/file_on_host' )         println( "File on host, run from host: ${fileExists( '/tmp/file_on_host' )}" ) // true         docker.image( "ubuntu:latest" ).inside() {             sh( 'date > /tmp/file_in_docker' )             println( "File on host, run from docker: ${fileExists( '/tmp/file_on_host' )}" ) // true             println( "File in docker, run from docker: ${fileExists( '/tmp/file_in_docker' )}" ) // false         }     } }     To check presence of file inside docker container, you can use something like: boolean isPresent = sh(script: "test -f ${filePath}" , returnStatus: true ) == 0

            Unassigned Unassigned
            akom Alexander Komarov
            Votes:
            3 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated: