title: Jenkins Golang Declarative Pipeline: Build Docker Image and Push to Docker Hub
body: <p>I'm trying to create a Docker image of my Golang project and upload it to Docker Hub via Jenkins Declarative Pipeline.</p>
  
  <p>I am able to build my project and run all my tests.</p>
  
  <p>My <code>Jenkinsfile</code> is as follows:</p>
  
  <pre><code>#!/usr/bin/env groovy
  // The above line is used to trigger correct syntax highlighting.
  
  pipeline {
      agent { docker { image 'golang' } }
  
      stages {
          stage('Build') {   
              steps {                                           
                  // Create our project directory.
                  sh 'cd ${GOPATH}/src'
                  sh 'mkdir -p ${GOPATH}/src/MY_PROJECT_DIRECTORY'
  
                  // Copy all files in our Jenkins workspace to our project directory.                
                  sh 'cp -r ${WORKSPACE}/* ${GOPATH}/src/MY_PROJECT_DIRECTORY'
  
                  // Copy all files in our "vendor" folder to our "src" folder.
                  sh 'cp -r ${WORKSPACE}/vendor/* ${GOPATH}/src'
  
                  // Build the app.
                  sh 'go build'
              }            
          }
  
          // Each "sh" line (shell command) is a step,
          // so if anything fails, the pipeline stops.
          stage('Test') {
              steps {                                
                  // Remove cached test results.
                  sh 'go clean -cache'
  
                  // Run Unit Tests.
                  sh 'go test ./... -v'                                  
              }
          }           
      }
  }   
  </code></pre>
  
  <p>My <code>Dockerfile</code> (if needed) is as follows:</p>
  
  <pre><code># Make a golang container from the "golang alpine" docker image from Docker Hub.
  FROM golang:1.11.2-alpine3.8
  
  # Expose our desired port.
  EXPOSE 9000
  
  # Create the proper directory.
  RUN mkdir -p $GOPATH/src/MY_PROJECT_DIRECTORY
  
  # Copy app to the proper directory for building.
  ADD . $GOPATH/src/MY_PROJECT_DIRECTORY
  
  # Set the work directory.
  WORKDIR $GOPATH/src/MY_PROJECT_DIRECTORY
  
  # Run CMD commands.
  RUN go get -d -v ./...
  RUN go install -v ./...
  
  # Provide defaults when running the container.
  # These will be executed after the entrypoint.
  # For example, if you ran docker run &lt;image&gt;,
  # then the commands and parameters specified by CMD would be executed.
  CMD ["MY_PROJECT"]
  </code></pre>
  
  <p>I am able to get my Docker Hub credentials via:</p>
  
  <pre><code>environment {
      // Extract the username and password of our credentials into "DOCKER_CREDENTIALS_USR" and "DOCKER_CREDENTIALS_PSW".
      // (NOTE 1: DOCKER_CREDENTIALS will be set to "your_username:your_password".)
      // The new variables will always be YOUR_VARIABLE_NAME + _USR and _PSW.
      DOCKER_CREDENTIALS = credentials('MY_JENKINS_CREDENTIAL_ID')
  }
  </code></pre>
  
  <p>For reference, here is what I got to work in my Freestyle job:</p>
  
  <pre><code>Execute Shell:
  
      # Log in to Docker.
      sudo docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
  
      # Make a Docker image for our app.
      cd /var/lib/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/Go/src/MY_PROJECT_DIRECTORY/
      sudo docker build -t MY-PROJECT-img .
  
      # Tag our Docker image.
      sudo docker tag  MY-PROJECT-img   $DOCKER_USERNAME/MY-PROJECT-img
  
      # Push our Docker image to Docker Hub.
      sudo docker push $DOCKER_USERNAME/MY-PROJECT-img
  
      # Log out of Docker.
      docker logout
  </code></pre>
  
  <p>NOTE: I have given Jenkins sudo privileges by doing the following:</p>
  
  <ol>
  <li><p>Open the sudoers file for editing:</p>
  
  <p>sudo visudo -f /etc/sudoers</p></li>
  <li><p>Press "i" to go into INSERT mode.</p></li>
  <li><p>Paste the following:</p>
  
  <p>jenkins ALL=(ALL) NOPASSWD: ALL</p></li>
  <li><p>Press "ESC" to exit INSERT mode.</p></li>
  <li><p>To Save, enter:</p>
  
  <p>:w</p></li>
  <li><p>To Quit, enter:</p>
  
  <p>:q</p></li>
  </ol>
  
  <p>I believe this should be possible by adding a new <code>stage</code> and <code>agent</code> in my Declarative Pipeline, but I haven't found anything online.</p>