22

I am creating Jenkins pipeline for running terraform on a Docker container.

Here is my pipeline script.

pipeline {
    agent {
        docker {
            image 'hashicorp/terraform:full'
            args '--entrypoint=/bin/bash'
        }
    }
    stages {
        stage('execute') { 
            steps {
                sh 'terraform --version' 
            }
        }
    }
}

When running this pipeline on Jenkins, I get the below error.

$ docker run -t -d -u 995:993 --entrypoint=/bin/bash -w /var/lib/jenkins/workspace/terraform -v /var/lib/jenkins/workspace/terraform:/var/lib/jenkins/workspace/terraform:rw,z -v /var/lib/jenkins/workspace/terraform@tmp:/var/lib/jenkins/workspace/terraform@tmp:rw,z -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** hashicorp/terraform:full cat

$ docker top a0b801d657d0fffdfa95c387564128b130ab1d28569ad59bd0151c8b7faf6ffd -eo pid,comm

java.io.IOException: Failed to run top 'a0b801d657d0fffdfa95c387564128b130ab1d28569ad59bd0151c8b7faf6ffd'. Error: Error response from daemon: Container a0b801d657d0fffdfa95c387564128b130ab1d28569ad59bd0151c8b7faf6ffd is not running

This seems like Jenkins add a cat command to run the image hashicorp/terraform:full.

Note that, I have overridden the entrypoint to /bin/bash using --entrypoint=/bin/bash since hashicorp/terraform:full already has an entrypoint defined.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Param
  • 313
  • 1
  • 2
  • 11
  • Is your question about why the `cat` command is being added to the `run`, or is it why you are getting your error and how to fix it? Those two questions are unrelated. – Matthew Schuchard Mar 27 '19 at 13:11
  • 5
    The `cat` is a hack to keep the container's main process open indefinitely until the job ends. It replaces a container's `CMD`. The container is started detached and then another process attaches to it so that console commands can run. Personally, I'm not fond of the approach. – ingyhere Aug 29 '20 at 03:39
  • 1
    It's **super lame** because containers don't always work out of the box, and if you set up a chained system between entrypoint and command it doesn't work as designed. It's a hack in Jenkins, so I agree with this commenter that the [fix should be in the Jenkinsfile](https://issues.jenkins-ci.org/browse/JENKINS-51307?focusedCommentId=342021&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-342021). In fact, your `entrypoint` could run senselessly, and it breaks the [paradigm of entrypoint-cmd](https://stackoverflow.com/a/39408777/325452) relationships. – ingyhere Aug 29 '20 at 03:45
  • Because the native `cmd` doesn't run and `entrypoint` may be rendered useless, you must issue `sh` commands that mirror them in the Jenkins pipeline. – ingyhere Aug 29 '20 at 03:49

3 Answers3

22

I had to change the ENTRYPOINT to empty to disable the entrypoint definition from the terraform container definition. And I think the light image is sufficient for just executing terraform.

I got it working with the following script:

pipeline {
  agent {
    docker {
        image 'hashicorp/terraform:light'
        args '--entrypoint='
    }
  }
  stages {
    stage('execute') { 
        steps {
            sh 'terraform --version' 
        }
    }
  }
}
S.Spieker
  • 7,005
  • 8
  • 44
  • 50
4

This seems to be a default behavior of docker-workflow-plugin in jenkins. [FIXED JENKINS-41316] Switch 'inside' back to CMD, detect if entrypoint was badly designed #116 https://github.com/jenkinsci/docker-workflow-plugin/pull/116

we run whatever the process the image specifies (even sh -c) Their purpose is That will break in most images, since for this purpose we need to start a container, pause it while we exec some stuff, and then stop it, without having to guess what its “main command” might run and when it might exit on its own. That is why we cat (I also have considered sleep infinity or some POSIX-compliant variant).

https://issues.jenkins-ci.org/browse/JENKINS-39748

code is here: https://github.com/jenkinsci/docker-workflow-plugin/blob/50ad50bad2ee14eb73d1ae3ef1058b8ad76c9e5d/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java#L184

They want the container will be /* expected to hang until killed */.


Original answer:

Would you try to run without -d option(which means run in background)

docker run -it --entrypoint=/bin/bash hashicorp/terraform:full

Then you can enter the container to run whatever you want.

Take nginx as an example:

docker run -it --entrypoint=/bin/bash nginx
root@e4dc1d08de1d:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@e4dc1d08de1d:/# cat /var/log/
apt/      btmp      dpkg.log  faillog   lastlog   nginx/    wtmp
root@e4dc1d08de1d:/# cat /var/log/faillog
root@e4dc1d08de1d:/#
paco alcacer
  • 381
  • 2
  • 13
  • 7
    The *docker run* command is generated by Jenkins server from the pipeline configuration and is not directly editable. – Param Mar 27 '19 at 04:50
3

in my case, the entrypoint did some troubles for me so I needed to overwrite it by passing empty entrypoint argument to the inside method like here:

pipeline {
    agent { 
        label 'some_label'
    }
    stages {
        stage('execute') { 
            steps {
                script {
                    img = docker.build("docker_image_name:docker_image_tag")
                    
                    img.inside('--entrypoint= -e NODE_ENV=test') {
                        sh 'npm install --dev'
                        sh 'npm run test'
                    }                   
                }
            }
        }
    }
}

this example is like @S.Spieker comment but with different syntax.

remark: npm commands like npm test can be different between node js projects, so you will need to get the relevant commands from the developer.

if this example is still not working for you so you probably need to change your docker image entrypoint like here: https://github.com/SonarSource/sonar-scanner-cli-docker/pull/31/files

you can learn more about the docker-flow plugin here: https://docs.cloudbees.com/docs/admin-resources/latest/plugins/docker-workflow

some more examples: Jenkins: How to use JUnit plugin when Maven builds occur within Docker container

dsaydon
  • 4,421
  • 6
  • 48
  • 52