2

I am using docker to simulate postgres database for my app. I was testing it in Cypress for some time and it works fine. I want to set up Jenkins for further testing, but I seem stuck.

On my device, I would use commands

docker create -e POSTGRES_DB=myDB -p 127.0.0.1:5432:5432 --name myDB postgres docker start myDB

to create it. How can I simulate this in Jenkins pipeline? I need the DB for the app to work.

I use Dockerfile as my agent, and I have tried putting the ENV variables there, but it does not work. Docker is not installed on the pipeline.

The way I see it is either:

  1. Create an image by using a
  2. Somehow install docker inside the pipeline and use the same commands
  3. Maybe with master/slave nodes? I don't understand them well yet.

2 Answers 2

3

This might be a use case for sidecar pattern one of Jenkins Pipeline's advanced features.

For example (from the above site):

node {
    checkout scm
    docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c ->
        docker.image('mysql:5').inside("--link ${c.id}:db") {
            /* Wait until mysql service is up */
            sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
        }
        docker.image('centos:7').inside("--link ${c.id}:db") {
            /*
             * Run some tests which require MySQL, and assume that it is
             * available on the host name `db`
             */
            sh 'make check'
        }
    }
}

The above example uses the object exposed by withRun, which has the running container’s ID available via the id property. Using the container’s ID, the Pipeline can create a link by passing custom Docker arguments to the inside() method.

Best thing is that the containers should be automatically stopped and removed when the work is done.

EDIT:
To use docker network instead you can do the following (open Jira to support this OOTB). Following helper function

def withDockerNetwork(Closure inner) {
    try {
        networkId = UUID.randomUUID().toString()
        sh "docker network create ${networkId}"
        inner.call(networkId)
    } finally {
        sh "docker network rm ${networkId}"
    }
}

Actual usage

withDockerNetwork{ n ->
   docker.image('sidecar').withRun("--network ${n} --name sidecar") { c->
      docker.image('main').inside("--network ${n}") {
         // do something with host "sidecar"
      }
   }
} 
Sign up to request clarification or add additional context in comments.

2 Comments

This should not be used anymore since the link feature is deprecated by docker. docs.docker.com/network/links
Updated the answer to cover this with same randomly generated docker network.
-2

For declarative pipelines:

pipeline {
  agent any
  environment {
    POSTGRES_HOST = 'localhost'
    POSTGRES_USER = myuser'
  }

  stages {
    stage('run!') {
      steps {
        script {
            docker.image('postgres:9.6').withRun(
                "-h ${env.POSTGRES_HOST} -e POSTGRES_USER=${env.POSTGRES_USER}"
            ) { db ->
// You can your image here but you need psql to be installed inside
                docker.image('postgres:9.6').inside("--link ${db.id}:db") {
                  sh '''
psql --version
until psql -h ${POSTGRES_HOST} -U ${POSTGRES_USER} -c "select 1" > /dev/null 2>&1 || [ $RETRIES -eq 0 ]; do
  echo "Waiting for postgres server, $((RETRIES-=1)) remaining attempts..."
  sleep 1
done
'''
                  sh 'echo "your commands here"'
                }
              }
            }
      }
    }
  }
}

Related to Docker wait for postgresql to be running

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.